1 /* 2 * Copyright (C) 2013 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 androidx.core.content; 18 19 import static android.os.Build.VERSION.SDK_INT; 20 21 import android.content.ContentResolver; 22 import android.database.Cursor; 23 import android.net.Uri; 24 25 import androidx.core.os.CancellationSignal; 26 import androidx.core.os.OperationCanceledException; 27 28 /** 29 * Helper for accessing features in {@link android.content.ContentResolver} in a backwards 30 * compatible fashion. 31 */ 32 public final class ContentResolverCompat { 33 private ContentResolverCompat() { 34 /* Hide constructor */ 35 } 36 37 /** 38 * Query the given URI, returning a {@link Cursor} over the result set 39 * with optional support for cancellation. 40 * <p> 41 * For best performance, the caller should follow these guidelines: 42 * <ul> 43 * <li>Provide an explicit projection, to prevent 44 * reading data from storage that aren't going to be used.</li> 45 * <li>Use question mark parameter markers such as 'phone=?' instead of 46 * explicit values in the {@code selection} parameter, so that queries 47 * that differ only by those values will be recognized as the same 48 * for caching purposes.</li> 49 * </ul> 50 * </p> 51 * 52 * @param uri The URI, using the content:// scheme, for the content to 53 * retrieve. 54 * @param projection A list of which columns to return. Passing null will 55 * return all columns, which is inefficient. 56 * @param selection A filter declaring which rows to return, formatted as an 57 * SQL WHERE clause (excluding the WHERE itself). Passing null will 58 * return all rows for the given URI. 59 * @param selectionArgs You may include ?s in selection, which will be 60 * replaced by the values from selectionArgs, in the order that they 61 * appear in the selection. The values will be bound as Strings. 62 * @param sortOrder How to order the rows, formatted as an SQL ORDER BY 63 * clause (excluding the ORDER BY itself). Passing null will use the 64 * default sort order, which may be unordered. 65 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 66 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 67 * when the query is executed. 68 * @return A Cursor object, which is positioned before the first entry, or null 69 * @see Cursor 70 */ 71 public static Cursor query(ContentResolver resolver, 72 Uri uri, String[] projection, String selection, String[] selectionArgs, 73 String sortOrder, CancellationSignal cancellationSignal) { 74 if (SDK_INT >= 16) { 75 try { 76 final android.os.CancellationSignal cancellationSignalObj = 77 (android.os.CancellationSignal) 78 (cancellationSignal != null 79 ? cancellationSignal.getCancellationSignalObject() 80 : null); 81 return resolver.query(uri, projection, selection, selectionArgs, sortOrder, 82 cancellationSignalObj); 83 } catch (Exception e) { 84 if (e instanceof android.os.OperationCanceledException) { 85 // query() can throw a framework OperationCanceledException if it has been 86 // canceled. We catch that and throw the support version instead. 87 throw new OperationCanceledException(); 88 } else { 89 // If it's not a framework OperationCanceledException, re-throw the exception 90 throw e; 91 } 92 } 93 } else { 94 // Note that the cancellation signal cannot cancel the query in progress 95 // prior to Jellybean so we cancel it preemptively here if needed. 96 if (cancellationSignal != null) { 97 cancellationSignal.throwIfCanceled(); 98 } 99 return resolver.query(uri, projection, selection, selectionArgs, sortOrder); 100 } 101 } 102 } 103