1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.content; 18 19 import android.annotation.NonNull; 20 import android.net.Uri; 21 22 import java.util.List; 23 24 /** 25 * Utility methods useful for working with {@link android.net.Uri} objects 26 * that use the "content" (content://) scheme. 27 * 28 *<p> 29 * Content URIs have the syntax 30 *</p> 31 *<p> 32 * <code>content://<em>authority</em>/<em>path</em>/<em>id</em></code> 33 *</p> 34 *<dl> 35 * <dt> 36 * <code>content:</code> 37 * </dt> 38 * <dd> 39 * The scheme portion of the URI. This is always set to {@link 40 * android.content.ContentResolver#SCHEME_CONTENT ContentResolver.SCHEME_CONTENT} (value 41 * <code>content://</code>). 42 * </dd> 43 * <dt> 44 * <em>authority</em> 45 * </dt> 46 * <dd> 47 * A string that identifies the entire content provider. All the content URIs for the provider 48 * start with this string. To guarantee a unique authority, providers should consider 49 * using an authority that is the same as the provider class' package identifier. 50 * </dd> 51 * <dt> 52 * <em>path</em> 53 * </dt> 54 * <dd> 55 * Zero or more segments, separated by a forward slash (<code>/</code>), that identify 56 * some subset of the provider's data. Most providers use the path part to identify 57 * individual tables. Individual segments in the path are often called 58 * "directories" although they do not refer to file directories. The right-most 59 * segment in a path is often called a "twig" 60 * </dd> 61 * <dt> 62 * <em>id</em> 63 * </dt> 64 * <dd> 65 * A unique numeric identifier for a single row in the subset of data identified by the 66 * preceding path part. Most providers recognize content URIs that contain an id part 67 * and give them special handling. A table that contains a column named <code>_ID</code> 68 * often expects the id part to be a particular value for that column. 69 * </dd> 70 *</dl> 71 * 72 */ 73 @android.ravenwood.annotation.RavenwoodKeepWholeClass 74 public class ContentUris { 75 76 /** 77 * Converts the last path segment to a long. 78 * 79 * <p>This supports a common convention for content URIs where an ID is 80 * stored in the last segment. 81 * 82 * @throws UnsupportedOperationException if this isn't a hierarchical URI 83 * @throws NumberFormatException if the last segment isn't a number 84 * 85 * @return the long conversion of the last segment or -1 if the path is 86 * empty 87 */ parseId(@onNull Uri contentUri)88 public static long parseId(@NonNull Uri contentUri) { 89 String last = contentUri.getLastPathSegment(); 90 return last == null ? -1 : Long.parseLong(last); 91 } 92 93 /** 94 * Appends the given ID to the end of the path. 95 * 96 * @param builder to append the ID to 97 * @param id to append 98 * 99 * @return the given builder 100 */ appendId(@onNull Uri.Builder builder, long id)101 public static @NonNull Uri.Builder appendId(@NonNull Uri.Builder builder, long id) { 102 return builder.appendEncodedPath(String.valueOf(id)); 103 } 104 105 /** 106 * Appends the given ID to the end of the path. 107 * 108 * @param contentUri to start with 109 * @param id to append 110 * 111 * @return a new URI with the given ID appended to the end of the path 112 */ withAppendedId(@onNull Uri contentUri, long id)113 public static @NonNull Uri withAppendedId(@NonNull Uri contentUri, long id) { 114 return appendId(contentUri.buildUpon(), id).build(); 115 } 116 117 /** 118 * Removes any ID from the end of the path. 119 * 120 * @param contentUri that ends with an ID 121 * @return a new URI with the ID removed from the end of the path 122 * @throws IllegalArgumentException when the given URI has no ID to remove 123 * from the end of the path 124 */ removeId(@onNull Uri contentUri)125 public static @NonNull Uri removeId(@NonNull Uri contentUri) { 126 // Verify that we have a valid ID to actually remove 127 final String last = contentUri.getLastPathSegment(); 128 if (last == null) { 129 throw new IllegalArgumentException("No path segments to remove"); 130 } else { 131 Long.parseLong(last); 132 } 133 134 final List<String> segments = contentUri.getPathSegments(); 135 final Uri.Builder builder = contentUri.buildUpon(); 136 builder.path(null); 137 for (int i = 0; i < segments.size() - 1; i++) { 138 builder.appendPath(segments.get(i)); 139 } 140 return builder.build(); 141 } 142 } 143