1220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown/* 2220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Copyright (C) 2013 The Android Open Source Project 3220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 4220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * you may not use this file except in compliance with the License. 6220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * You may obtain a copy of the License at 7220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 8220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 10220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Unless required by applicable law or agreed to in writing, software 11220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * See the License for the specific language governing permissions and 14220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * limitations under the License. 15220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 16220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 17220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownpackage android.support.v4.content; 18220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 19220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.content.ContentResolver; 20220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.database.Cursor; 21220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.net.Uri; 22220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.os.Build; 23220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.support.v4.os.CancellationSignal; 24220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brownimport android.support.v4.os.OperationCanceledException; 25220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 26220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown/** 27220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Helper for accessing features in {@link android.content.ContentResolver} 28220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * introduced after API level 4 in a backwards compatible fashion. 29220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 30c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class ContentResolverCompat { 31220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown interface ContentResolverCompatImpl { 32220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown Cursor query(ContentResolver resolver, 33220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown Uri uri, String[] projection, String selection, String[] selectionArgs, 34220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown String sortOrder, CancellationSignal cancellationSignal); 35220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 36220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 37220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown static class ContentResolverCompatImplBase implements ContentResolverCompatImpl { 38220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown @Override 39220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public Cursor query(ContentResolver resolver, Uri uri, String[] projection, 40220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown String selection, String[] selectionArgs, String sortOrder, 41220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown CancellationSignal cancellationSignal) { 42220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown // Note that the cancellation signal cannot cancel the query in progress 43220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown // prior to Jellybean so we cancel it preemptively here if needed. 44220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (cancellationSignal != null) { 45220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown cancellationSignal.throwIfCanceled(); 46220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 47220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown return resolver.query(uri, projection, selection, selectionArgs, sortOrder); 48220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 49220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 50220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 51220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown static class ContentResolverCompatImplJB extends ContentResolverCompatImplBase { 52220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown @Override 53220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public Cursor query(ContentResolver resolver, Uri uri, String[] projection, 54220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown String selection, String[] selectionArgs, String sortOrder, 55220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown CancellationSignal cancellationSignal) { 5694d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes try { 5794d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes return ContentResolverCompatJellybean.query(resolver, 5894d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes uri, projection, selection, selectionArgs, sortOrder, 5994d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes cancellationSignal != null ? 6094d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes cancellationSignal.getCancellationSignalObject() : null); 6194d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes } catch (Exception e) { 6294d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes if (ContentResolverCompatJellybean.isFrameworkOperationCanceledException(e)) { 6394d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes // query() can throw a framework OperationCanceledException if it has been 6494d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes // canceled. We catch that and throw the support version instead. 6594d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes throw new OperationCanceledException(); 6694d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes } else { 6794d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes // If it's not a framework OperationCanceledException, re-throw the exception 6894d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes throw e; 6994d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes } 7094d7acd9d29354189ef9c7caeb372363043f7df7Chris Banes } 71220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 72220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 73220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 74220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown private static final ContentResolverCompatImpl IMPL; 75220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown static { 76220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown final int version = Build.VERSION.SDK_INT; 77220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown if (version >= 16) { 78220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown IMPL = new ContentResolverCompatImplJB(); 79220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } else { 80220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown IMPL = new ContentResolverCompatImplBase(); 81220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 82220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 83220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 84220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown private ContentResolverCompat() { 85220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /* Hide constructor */ 86220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 87220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown 88220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown /** 89220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * Query the given URI, returning a {@link Cursor} over the result set 90220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * with optional support for cancellation. 91220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * <p> 92220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * For best performance, the caller should follow these guidelines: 93220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * <ul> 94220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * <li>Provide an explicit projection, to prevent 95220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * reading data from storage that aren't going to be used.</li> 96220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * <li>Use question mark parameter markers such as 'phone=?' instead of 97220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * explicit values in the {@code selection} parameter, so that queries 98220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * that differ only by those values will be recognized as the same 99220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * for caching purposes.</li> 100220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * </ul> 101220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * </p> 102220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * 103220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @param uri The URI, using the content:// scheme, for the content to 104220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * retrieve. 105220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @param projection A list of which columns to return. Passing null will 106220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * return all columns, which is inefficient. 107220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @param selection A filter declaring which rows to return, formatted as an 108220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * SQL WHERE clause (excluding the WHERE itself). Passing null will 109220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * return all rows for the given URI. 110220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @param selectionArgs You may include ?s in selection, which will be 111220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * replaced by the values from selectionArgs, in the order that they 112220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * appear in the selection. The values will be bound as Strings. 113220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @param sortOrder How to order the rows, formatted as an SQL ORDER BY 114220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * clause (excluding the ORDER BY itself). Passing null will use the 115220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * default sort order, which may be unordered. 116220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 117220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * If the operation is canceled, then {@link OperationCanceledException} will be thrown 118220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * when the query is executed. 119220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @return A Cursor object, which is positioned before the first entry, or null 120220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown * @see Cursor 121220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown */ 122220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown public static Cursor query(ContentResolver resolver, 123220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown Uri uri, String[] projection, String selection, String[] selectionArgs, 124220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown String sortOrder, CancellationSignal cancellationSignal) { 125220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown return IMPL.query(resolver, uri, projection, selection, selectionArgs, 126220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown sortOrder, cancellationSignal); 127220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown } 128220dc21ab5a2a5b3f8b6532105121750770a69f4Jeff Brown} 129