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 public class ContentUris { 74 75 /** 76 * Converts the last path segment to a long. 77 * 78 * <p>This supports a common convention for content URIs where an ID is 79 * stored in the last segment. 80 * 81 * @throws UnsupportedOperationException if this isn't a hierarchical URI 82 * @throws NumberFormatException if the last segment isn't a number 83 * 84 * @return the long conversion of the last segment or -1 if the path is 85 * empty 86 */ parseId(@onNull Uri contentUri)87 public static long parseId(@NonNull Uri contentUri) { 88 String last = contentUri.getLastPathSegment(); 89 return last == null ? -1 : Long.parseLong(last); 90 } 91 92 /** 93 * Appends the given ID to the end of the path. 94 * 95 * @param builder to append the ID to 96 * @param id to append 97 * 98 * @return the given builder 99 */ appendId(@onNull Uri.Builder builder, long id)100 public static @NonNull Uri.Builder appendId(@NonNull Uri.Builder builder, long id) { 101 return builder.appendEncodedPath(String.valueOf(id)); 102 } 103 104 /** 105 * Appends the given ID to the end of the path. 106 * 107 * @param contentUri to start with 108 * @param id to append 109 * 110 * @return a new URI with the given ID appended to the end of the path 111 */ withAppendedId(@onNull Uri contentUri, long id)112 public static @NonNull Uri withAppendedId(@NonNull Uri contentUri, long id) { 113 return appendId(contentUri.buildUpon(), id).build(); 114 } 115 116 /** 117 * Removes any ID from the end of the path. 118 * 119 * @param contentUri that ends with an ID 120 * @return a new URI with the ID removed from the end of the path 121 * @throws IllegalArgumentException when the given URI has no ID to remove 122 * from the end of the path 123 */ removeId(@onNull Uri contentUri)124 public static @NonNull Uri removeId(@NonNull Uri contentUri) { 125 // Verify that we have a valid ID to actually remove 126 final String last = contentUri.getLastPathSegment(); 127 if (last == null) { 128 throw new IllegalArgumentException("No path segments to remove"); 129 } else { 130 Long.parseLong(last); 131 } 132 133 final List<String> segments = contentUri.getPathSegments(); 134 final Uri.Builder builder = contentUri.buildUpon(); 135 builder.path(null); 136 for (int i = 0; i < segments.size() - 1; i++) { 137 builder.appendPath(segments.get(i)); 138 } 139 return builder.build(); 140 } 141 } 142