1b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio/* 2b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Copyright (C) 2014 The Android Open Source Project 3b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 4b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License"); 5b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * you may not use this file except in compliance with the License. 6b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * You may obtain a copy of the License at 7b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 8b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * http://www.apache.org/licenses/LICENSE-2.0 9b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 10b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Unless required by applicable law or agreed to in writing, software 11b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS, 12b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * See the License for the specific language governing permissions and 14b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * limitations under the License. 15b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 16b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 17b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Megliopackage android.provider; 18b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 1927e13347344276f337d4289e3197f8ab7d5c74d2Fabrice Di Meglioimport android.annotation.SystemApi; 20b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.ContentProvider; 21b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.ContentValues; 22b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.Context; 23b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.UriMatcher; 24b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.pm.ProviderInfo; 25b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.database.Cursor; 26b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.net.Uri; 27b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 28b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio/** 29b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Base class for a search indexable provider. Such provider offers data to be indexed either 30b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * as a reference to an XML file (like a {@link android.preference.PreferenceScreen}) or either 31b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * as some raw data. 32b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 33b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @see SearchIndexableResource 34b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @see SearchIndexableData 35b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @see SearchIndexablesContract 36b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 37b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * To create a search indexables provider, extend this class, then implement the abstract methods, 38b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * and add it to your manifest like this: 39b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 40b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <pre class="prettyprint"><manifest> 41b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * ... 42b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <application> 43b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * ... 44b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <provider 45b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:name="com.example.MyIndexablesProvider" 46b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:authorities="com.example.myindexablesprovider" 47b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:exported="true" 48b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:grantUriPermissions="true" 49b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:permission="android.permission.READ_SEARCH_INDEXABLES" 50b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <intent-filter> 51b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" /> 52b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * </intent-filter> 53b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * </provider> 54b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * ... 55b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * </application> 56b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *</manifest></pre> 57b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <p> 58b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * When defining your provider, you must protect it with 59b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * {@link android.Manifest.permission#READ_SEARCH_INDEXABLES}, which is a permission only the system 60b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * can obtain. 61b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * </p> 62b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 63b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @hide 64b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 6527e13347344276f337d4289e3197f8ab7d5c74d2Fabrice Di Meglio@SystemApi 66b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Megliopublic abstract class SearchIndexablesProvider extends ContentProvider { 67b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private static final String TAG = "IndexablesProvider"; 68b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 69b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private String mAuthority; 70b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private UriMatcher mMatcher; 71b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 72b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private static final int MATCH_RES_CODE = 1; 73b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private static final int MATCH_RAW_CODE = 2; 7497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio private static final int MATCH_NON_INDEXABLE_KEYS_CODE = 3; 75b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 76b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 77b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Implementation is provided by the parent class. 78b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 79b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 80b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public void attachInfo(Context context, ProviderInfo info) { 81b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio mAuthority = info.authority; 82b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 83b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio mMatcher = new UriMatcher(UriMatcher.NO_MATCH); 84b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio mMatcher.addURI(mAuthority, SearchIndexablesContract.INDEXABLES_XML_RES_PATH, 85b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio MATCH_RES_CODE); 86b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio mMatcher.addURI(mAuthority, SearchIndexablesContract.INDEXABLES_RAW_PATH, 87b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio MATCH_RAW_CODE); 8897babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio mMatcher.addURI(mAuthority, SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH, 8997babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio MATCH_NON_INDEXABLE_KEYS_CODE); 90b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 91b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio // Sanity check our setup 92b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio if (!info.exported) { 93b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new SecurityException("Provider must be exported"); 94b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 95b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio if (!info.grantUriPermissions) { 96b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new SecurityException("Provider must grantUriPermissions"); 97b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 98b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio if (!android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(info.readPermission)) { 99b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new SecurityException("Provider must be protected by READ_SEARCH_INDEXABLES"); 100b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 101b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 102b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio super.attachInfo(context, info); 103b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 104b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 105b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 106b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 107b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio String sortOrder) { 108b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio switch (mMatcher.match(uri)) { 109b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio case MATCH_RES_CODE: 110b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio return queryXmlResources(null); 111b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio case MATCH_RAW_CODE: 112b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio return queryRawData(null); 11397babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio case MATCH_NON_INDEXABLE_KEYS_CODE: 11497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio return queryNonIndexableKeys(null); 115b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio default: 116b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new UnsupportedOperationException("Unknown Uri " + uri); 117b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 118b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 119b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 120b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 121b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Returns all {@link android.provider.SearchIndexablesContract.XmlResource}. 122b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 12397babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Those are Xml resource IDs to some {@link android.preference.PreferenceScreen}. 124b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 125b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @param projection list of {@link android.provider.SearchIndexablesContract.XmlResource} 126b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * columns to put into the cursor. If {@code null} all supported columns 127b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * should be included. 128b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 129b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public abstract Cursor queryXmlResources(String[] projection); 130b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 131b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 132b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Returns all {@link android.provider.SearchIndexablesContract.RawData}. 133b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 13497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Those are the raw indexable data. 135b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 136b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @param projection list of {@link android.provider.SearchIndexablesContract.RawData} columns 137b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * to put into the cursor. If {@code null} all supported columns should be 138b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * included. 139b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 140b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public abstract Cursor queryRawData(String[] projection); 141b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 14297babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio /** 14397babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Returns all {@link android.provider.SearchIndexablesContract.NonIndexableKey}. 14497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * 14597babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Those are the non indexable data keys. 14697babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * 14797babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * @param projection list of {@link android.provider.SearchIndexablesContract.NonIndexableKey} 14897babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * columns to put into the cursor. If {@code null} all supported columns 14997babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * should be included. 15097babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio */ 15197babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio public abstract Cursor queryNonIndexableKeys(String[] projection); 15297babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio 153b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 154b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public String getType(Uri uri) { 155b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio switch (mMatcher.match(uri)) { 156b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio case MATCH_RES_CODE: 157b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio return SearchIndexablesContract.XmlResource.MIME_TYPE; 158b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio case MATCH_RAW_CODE: 159b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio return SearchIndexablesContract.RawData.MIME_TYPE; 16097babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio case MATCH_NON_INDEXABLE_KEYS_CODE: 16197babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio return SearchIndexablesContract.NonIndexableKey.MIME_TYPE; 162b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio default: 163b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new IllegalArgumentException("Unknown URI " + uri); 164b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 165b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 166b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 167b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 16897babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Implementation is provided by the parent class. Throws by default, and cannot be overriden. 169b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 170b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 171b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public final Uri insert(Uri uri, ContentValues values) { 172b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new UnsupportedOperationException("Insert not supported"); 173b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 174b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 175b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 17697babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Implementation is provided by the parent class. Throws by default, and cannot be overriden. 177b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 178b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 179b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public final int delete(Uri uri, String selection, String[] selectionArgs) { 180b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new UnsupportedOperationException("Delete not supported"); 181b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 182b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 183b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 18497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Implementation is provided by the parent class. Throws by default, and cannot be overriden. 185b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 186b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 187b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public final int update( 188b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio Uri uri, ContentValues values, String selection, String[] selectionArgs) { 189b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new UnsupportedOperationException("Update not supported"); 190b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 191b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio} 192