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