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 19b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.ContentProvider; 20b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.ContentValues; 21b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.Context; 22b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.UriMatcher; 23b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.content.pm.ProviderInfo; 24b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.database.Cursor; 25b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglioimport android.net.Uri; 26b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 27b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio/** 28b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Base class for a search indexable provider. Such provider offers data to be indexed either 29b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * as a reference to an XML file (like a {@link android.preference.PreferenceScreen}) or either 30b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * as some raw data. 31b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 32b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @see SearchIndexableResource 33b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @see SearchIndexableData 34b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @see SearchIndexablesContract 35b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 36b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * To create a search indexables provider, extend this class, then implement the abstract methods, 37b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * and add it to your manifest like this: 38b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 39b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <pre class="prettyprint"><manifest> 40b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * ... 41b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <application> 42b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * ... 43b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <provider 44b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:name="com.example.MyIndexablesProvider" 45b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:authorities="com.example.myindexablesprovider" 46b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:exported="true" 47b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:grantUriPermissions="true" 48b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * android:permission="android.permission.READ_SEARCH_INDEXABLES" 49b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <intent-filter> 50b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" /> 51b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * </intent-filter> 52b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * </provider> 53b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * ... 54b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * </application> 55b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio *</manifest></pre> 56b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * <p> 57b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * When defining your provider, you must protect it with 58b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * {@link android.Manifest.permission#READ_SEARCH_INDEXABLES}, which is a permission only the system 59b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * can obtain. 60b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * </p> 61b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 62b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @hide 63b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 64b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Megliopublic abstract class SearchIndexablesProvider extends ContentProvider { 65b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private static final String TAG = "IndexablesProvider"; 66b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 67b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private String mAuthority; 68b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private UriMatcher mMatcher; 69b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 70b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private static final int MATCH_RES_CODE = 1; 71b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio private static final int MATCH_RAW_CODE = 2; 7297babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio private static final int MATCH_NON_INDEXABLE_KEYS_CODE = 3; 73b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 74b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 75b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Implementation is provided by the parent class. 76b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 77b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 78b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public void attachInfo(Context context, ProviderInfo info) { 79b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio mAuthority = info.authority; 80b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 81b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio mMatcher = new UriMatcher(UriMatcher.NO_MATCH); 82b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio mMatcher.addURI(mAuthority, SearchIndexablesContract.INDEXABLES_XML_RES_PATH, 83b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio MATCH_RES_CODE); 84b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio mMatcher.addURI(mAuthority, SearchIndexablesContract.INDEXABLES_RAW_PATH, 85b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio MATCH_RAW_CODE); 8697babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio mMatcher.addURI(mAuthority, SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH, 8797babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio MATCH_NON_INDEXABLE_KEYS_CODE); 88b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 89b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio // Sanity check our setup 90b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio if (!info.exported) { 91b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new SecurityException("Provider must be exported"); 92b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 93b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio if (!info.grantUriPermissions) { 94b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new SecurityException("Provider must grantUriPermissions"); 95b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 96b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio if (!android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(info.readPermission)) { 97b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new SecurityException("Provider must be protected by READ_SEARCH_INDEXABLES"); 98b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 99b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 100b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio super.attachInfo(context, info); 101b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 102b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 103b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 104b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 105b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio String sortOrder) { 106b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio switch (mMatcher.match(uri)) { 107b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio case MATCH_RES_CODE: 108b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio return queryXmlResources(null); 109b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio case MATCH_RAW_CODE: 110b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio return queryRawData(null); 11197babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio case MATCH_NON_INDEXABLE_KEYS_CODE: 11297babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio return queryNonIndexableKeys(null); 113b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio default: 114b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new UnsupportedOperationException("Unknown Uri " + uri); 115b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 116b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 117b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 118b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 119b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Returns all {@link android.provider.SearchIndexablesContract.XmlResource}. 120b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 12197babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Those are Xml resource IDs to some {@link android.preference.PreferenceScreen}. 122b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 123b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @param projection list of {@link android.provider.SearchIndexablesContract.XmlResource} 124b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * columns to put into the cursor. If {@code null} all supported columns 125b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * should be included. 126b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 127b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public abstract Cursor queryXmlResources(String[] projection); 128b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 129b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 130b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * Returns all {@link android.provider.SearchIndexablesContract.RawData}. 131b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 13297babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Those are the raw indexable data. 133b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * 134b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * @param projection list of {@link android.provider.SearchIndexablesContract.RawData} columns 135b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * to put into the cursor. If {@code null} all supported columns should be 136b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio * included. 137b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 138b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public abstract Cursor queryRawData(String[] projection); 139b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 14097babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio /** 14197babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Returns all {@link android.provider.SearchIndexablesContract.NonIndexableKey}. 14297babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * 14397babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Those are the non indexable data keys. 14497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * 14597babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * @param projection list of {@link android.provider.SearchIndexablesContract.NonIndexableKey} 14697babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * columns to put into the cursor. If {@code null} all supported columns 14797babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * should be included. 14897babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio */ 14997babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio public abstract Cursor queryNonIndexableKeys(String[] projection); 15097babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio 151b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 152b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public String getType(Uri uri) { 153b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio switch (mMatcher.match(uri)) { 154b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio case MATCH_RES_CODE: 155b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio return SearchIndexablesContract.XmlResource.MIME_TYPE; 156b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio case MATCH_RAW_CODE: 157b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio return SearchIndexablesContract.RawData.MIME_TYPE; 15897babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio case MATCH_NON_INDEXABLE_KEYS_CODE: 15997babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio return SearchIndexablesContract.NonIndexableKey.MIME_TYPE; 160b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio default: 161b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new IllegalArgumentException("Unknown URI " + uri); 162b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 163b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 164b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 165b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 16697babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Implementation is provided by the parent class. Throws by default, and cannot be overriden. 167b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 168b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 169b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public final Uri insert(Uri uri, ContentValues values) { 170b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new UnsupportedOperationException("Insert not supported"); 171b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 172b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 173b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 17497babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Implementation is provided by the parent class. Throws by default, and cannot be overriden. 175b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 176b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 177b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public final int delete(Uri uri, String selection, String[] selectionArgs) { 178b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new UnsupportedOperationException("Delete not supported"); 179b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 180b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio 181b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio /** 18297babb1e9a2b859ff01a633edad8e2ac5b02ab8aFabrice Di Meglio * Implementation is provided by the parent class. Throws by default, and cannot be overriden. 183b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio */ 184b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio @Override 185b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio public final int update( 186b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio Uri uri, ContentValues values, String selection, String[] selectionArgs) { 187b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio throw new UnsupportedOperationException("Update not supported"); 188b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio } 189b49995d4d997bf086c2f3214ca410b2a30861b13Fabrice Di Meglio} 190