SearchableSource.java revision 883c1bf364e38c5b133afb55f8493a14b65f4dd4
13e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/* 23e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Copyright (C) 2009 The Android Open Source Project 33e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 43e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 53e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * you may not use this file except in compliance with the License. 63e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * You may obtain a copy of the License at 73e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 83e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 93e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * See the License for the specific language governing permissions and 143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * limitations under the License. 153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpackage com.android.quicksearchbox; 183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 19fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.app.PendingIntent; 203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.app.SearchManager; 21227180196cf8d92172cbb62f8ddaacf864be28e7Bjorn Bringertimport android.app.SearchableInfo; 223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.content.ComponentName; 233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.content.ContentResolver; 243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.content.Context; 25fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.content.Intent; 263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.content.pm.ActivityInfo; 273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.content.pm.PackageManager; 283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.content.pm.PackageManager.NameNotFoundException; 293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.database.Cursor; 303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.graphics.drawable.Drawable; 313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.net.Uri; 32fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.os.Bundle; 33fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.speech.RecognizerIntent; 343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.util.Log; 353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 36227180196cf8d92172cbb62f8ddaacf864be28e7Bjorn Bringertimport java.util.Arrays; 37227180196cf8d92172cbb62f8ddaacf864be28e7Bjorn Bringert 383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/** 393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Represents a single suggestion source, e.g. Contacts. 403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpublic class SearchableSource implements Source { 433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private static final boolean DBG = true; 450484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert private static final String TAG = "QSB.SearchableSource"; 463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 47fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // TODO: This should be exposed or moved to android-common, see http://b/issue?id=2440614 48fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // The extra key used in an intent to the speech recognizer for in-app voice search. 49fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private static final String EXTRA_CALLING_PACKAGE = "calling_package"; 50fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private final Context mContext; 523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private final SearchableInfo mSearchable; 543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private final ActivityInfo mActivityInfo; 563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Cached label for the activity 583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private CharSequence mLabel = null; 593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Cached icon for the activity 613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private Drawable.ConstantState mSourceIcon = null; 623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private final IconLoader mIconLoader; 643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public SearchableSource(Context context, SearchableInfo searchable) 663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert throws NameNotFoundException { 673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert ComponentName componentName = searchable.getSearchActivity(); 683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mContext = context; 693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSearchable = searchable; 703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mActivityInfo = context.getPackageManager().getActivityInfo(componentName, 0); 713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 72e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert mIconLoader = createIconLoader(context, searchable.getSuggestPackage()); 73e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert } 74e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert 75fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected Context getContext() { 76fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mContext; 77fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 78fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 79fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected SearchableInfo getSearchableInfo() { 80fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mSearchable; 81fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 82fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 83e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert private IconLoader createIconLoader(Context context, String providerPackage) { 84e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert if (providerPackage == null) return null; 85e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert try { 86e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert return new CachingIconLoader(new PackageIconLoader(context, providerPackage)); 87e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert } catch (PackageManager.NameNotFoundException ex) { 88e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert Log.e(TAG, "Suggestion provider package not found: " + providerPackage); 89e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert return null; 90e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert } 913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public ComponentName getComponentName() { 943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.getSearchActivity(); 953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 97d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert public String getFlattenedComponentName() { 98d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert return getComponentName().flattenToShortString(); 99d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert } 100d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert 101ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert public String getLogName() { 102883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert return getFlattenedComponentName(); 103ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 104ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 1053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public Drawable getIcon(String drawableId) { 106e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert return mIconLoader == null ? null : mIconLoader.getIcon(drawableId); 1073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public Uri getIconUri(String drawableId) { 110e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert return mIconLoader == null ? null : mIconLoader.getIconUri(drawableId); 1113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public CharSequence getLabel() { 1143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (mLabel == null) { 1153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Load label lazily 1163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mLabel = mActivityInfo.loadLabel(mContext.getPackageManager()); 1173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mLabel; 1193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public int getQueryThreshold() { 1223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.getSuggestThreshold(); 1233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1258d9d845323514c34bb07d6eb91146a975324fcedBjorn Bringert public CharSequence getSettingsDescription() { 126fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getText(mSearchable.getSettingsDescriptionId()); 1273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public Drawable getSourceIcon() { 1303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (mSourceIcon == null) { 1313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Load icon lazily 1323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert int iconRes = getSourceIconResource(); 1333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert PackageManager pm = mContext.getPackageManager(); 1343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Drawable icon = pm.getDrawable(mActivityInfo.packageName, iconRes, 1353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mActivityInfo.applicationInfo); 1363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Can't share Drawable instances, save constant state instead. 1373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSourceIcon = (icon != null) ? icon.getConstantState() : null; 1383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Optimization, return the Drawable the first time 1393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return icon; 1403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return (mSourceIcon != null) ? mSourceIcon.newDrawable() : null; 1423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public Uri getSourceIconUri() { 145d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert int resourceId = getSourceIconResource(); 146d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert return new Uri.Builder() 147d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) 148d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert .authority(getComponentName().getPackageName()) 149d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert .appendEncodedPath(String.valueOf(resourceId)) 150d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert .build(); 1513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private int getSourceIconResource() { 1543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert int icon = mActivityInfo.getIconResource(); 1553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return (icon != 0) ? icon : android.R.drawable.sym_def_app_icon; 1563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 158fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public boolean voiceSearchEnabled() { 159fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mSearchable.getVoiceSearchEnabled(); 160fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 161fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 162fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // TODO: not all apps handle ACTION_SEARCH properly, e.g. ApplicationsProvider. 163fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Maybe we should add a flag to searchable, so that QSB can hide the search button? 164fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public Intent createSearchIntent(String query, Bundle appData) { 165fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Intent intent = new Intent(Intent.ACTION_SEARCH); 166fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.setComponent(getComponentName()); 167fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 168fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // We need CLEAR_TOP to avoid reusing an old task that has other activities 169fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // on top of the one we want. 170fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 171fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.putExtra(SearchManager.USER_QUERY, query); 172fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.putExtra(SearchManager.QUERY, query); 173fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (appData != null) { 174fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.putExtra(SearchManager.APP_DATA, appData); 175fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 176fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return intent; 177fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 178fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 179fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public Intent createVoiceSearchIntent(Bundle appData) { 180fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (mSearchable.getVoiceSearchLaunchWebSearch()) { 181fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return WebCorpus.createVoiceWebSearchIntent(appData); 182fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } else if (mSearchable.getVoiceSearchLaunchRecognizer()) { 183fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return createVoiceAppSearchIntent(appData); 184fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 185fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return null; 186fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 187fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 188fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert /** 189fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * Create and return an Intent that can launch the voice search activity, perform a specific 190fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * voice transcription, and forward the results to the searchable activity. 191fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * 192fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * This code is copied from SearchDialog 193fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * 194fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * @return A completely-configured intent ready to send to the voice search activity 195fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert */ 196fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Intent createVoiceAppSearchIntent(Bundle appData) { 197fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert ComponentName searchActivity = mSearchable.getSearchActivity(); 198fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 199fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // create the necessary intent to set up a search-and-forward operation 200fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // in the voice search system. We have to keep the bundle separate, 201fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // because it becomes immutable once it enters the PendingIntent 202fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Intent queryIntent = new Intent(Intent.ACTION_SEARCH); 203fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert queryIntent.setComponent(searchActivity); 204fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert PendingIntent pending = PendingIntent.getActivity( 205fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getContext(), 0, queryIntent, PendingIntent.FLAG_ONE_SHOT); 206fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 207fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Now set up the bundle that will be inserted into the pending intent 208fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // when it's time to do the search. We always build it here (even if empty) 209fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // because the voice search activity will always need to insert "QUERY" into 210fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // it anyway. 211fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Bundle queryExtras = new Bundle(); 212fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (appData != null) { 213fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert queryExtras.putBundle(SearchManager.APP_DATA, appData); 214fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 215fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 216fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Now build the intent to launch the voice search. Add all necessary 217fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // extras to launch the voice recognizer, and then all the necessary extras 218fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // to forward the results to the searchable activity 219fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Intent voiceIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 220fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 221fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 222fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Add all of the configuration options supplied by the searchable's metadata 223fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String languageModel = getString(mSearchable.getVoiceLanguageModeId()); 224fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (languageModel == null) { 225fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert languageModel = RecognizerIntent.LANGUAGE_MODEL_FREE_FORM; 226fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 227fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String prompt = getString(mSearchable.getVoicePromptTextId()); 228fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String language = getString(mSearchable.getVoiceLanguageId()); 229fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert int maxResults = mSearchable.getVoiceMaxResults(); 230fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (maxResults <= 0) { 231fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert maxResults = 1; 232fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 233fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 234fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel); 235fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt); 236fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language); 237fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxResults); 238fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(EXTRA_CALLING_PACKAGE, 239fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert searchActivity == null ? null : searchActivity.toShortString()); 240fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 241fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Add the values that configure forwarding the results 242fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pending); 243fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT_BUNDLE, queryExtras); 244fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 245fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return voiceIntent; 246fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 247fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 248fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public SourceResult getSuggestions(String query, int queryLimit) { 2493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert try { 2503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Cursor cursor = getSuggestions(mContext, mSearchable, query, queryLimit); 2513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, toString() + "[" + query + "] returned."); 252fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return new CursorBackedSourceResult(query, cursor); 2533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } catch (RuntimeException ex) { 2543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Log.e(TAG, toString() + "[" + query + "] failed", ex); 255fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return new CursorBackedSourceResult(query); 2563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 25994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney public SuggestionCursor refreshShortcut(String shortcutId, String extraData) { 26094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney Cursor cursor = null; 26194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney try { 26294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney cursor = getValidationCursor(mContext, mSearchable, shortcutId, extraData); 26394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (DBG) Log.d(TAG, toString() + "[" + shortcutId + "] returned."); 26494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (cursor != null && cursor.getCount() > 0) { 26594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney cursor.moveToFirst(); 26694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 267fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return new CursorBackedSourceResult(null, cursor); 26894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } catch (RuntimeException ex) { 26994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney Log.e(TAG, toString() + "[" + shortcutId + "] failed", ex); 27094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (cursor != null) { 27194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney cursor.close(); 27294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 27394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney // TODO: Should we delete the shortcut even if the failure is temporary? 27494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney return null; 27594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 27694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 27794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 278fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private class CursorBackedSourceResult extends CursorBackedSuggestionCursor 279fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert implements SourceResult { 280fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 281fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public CursorBackedSourceResult(String userQuery) { 282fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert this(userQuery, null); 283fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 284fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 285fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public CursorBackedSourceResult(String userQuery, Cursor cursor) { 286fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert super(userQuery, cursor); 287fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 288fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 289fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public Source getSource() { 290fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return SearchableSource.this; 291fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 292fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 293fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert @Override 294fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public Source getSuggestionSource() { 295fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return SearchableSource.this; 296fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 297fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 298883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert public boolean isSuggestionShortcut() { 299883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert return false; 300883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert } 301883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert 302fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 303fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 3043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 3053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * This is a copy of {@link SearchManager#getSuggestions(SearchableInfo, String)}. 3063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 3073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private static Cursor getSuggestions(Context context, SearchableInfo searchable, String query, 3083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert int queryLimit) { 3093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (searchable == null) { 3103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return null; 3113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String authority = searchable.getSuggestAuthority(); 3143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (authority == null) { 3153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return null; 3163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Uri.Builder uriBuilder = new Uri.Builder() 3193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert .scheme(ContentResolver.SCHEME_CONTENT) 3203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert .authority(authority); 3213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // if content path provided, insert it now 3233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert final String contentPath = searchable.getSuggestPath(); 3243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (contentPath != null) { 3253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert uriBuilder.appendEncodedPath(contentPath); 3263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // append standard suggestion query path 3293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY); 3303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // get the query selection, may be null 3323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String selection = searchable.getSuggestSelection(); 3333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // inject query, either as selection args or inline 3343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String[] selArgs = null; 3353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (selection != null) { // use selection if provided 3363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert selArgs = new String[] { query }; 3373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } else { // no selection, use REST pattern 3383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert uriBuilder.appendPath(query); 3393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert uriBuilder.appendQueryParameter("limit", String.valueOf(queryLimit)); 3423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Uri uri = uriBuilder.build(); 3443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // finally, make the query 3463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) { 3473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Log.d(TAG, "query(" + uri + ",null," + selection + "," 3483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert + Arrays.toString(selArgs) + ",null)"); 3493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return context.getContentResolver().query(uri, null, selection, selArgs, null); 3513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 35394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney private static Cursor getValidationCursor(Context context, SearchableInfo searchable, 35494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney String shortcutId, String extraData) { 35594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney String authority = searchable.getSuggestAuthority(); 35694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (authority == null) { 35794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney return null; 35894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 35994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 36094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney Uri.Builder uriBuilder = new Uri.Builder() 36194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney .scheme(ContentResolver.SCHEME_CONTENT) 36294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney .authority(authority); 36394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 36494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney // if content path provided, insert it now 36594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney final String contentPath = searchable.getSuggestPath(); 36694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (contentPath != null) { 36794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney uriBuilder.appendEncodedPath(contentPath); 36894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 36994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 37094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney // append the shortcut path and id 37194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_SHORTCUT); 37294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney uriBuilder.appendPath(shortcutId); 37394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 37494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney Uri uri = uriBuilder 37594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney .appendQueryParameter(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA, extraData) 37694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney .build(); 37794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 37894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (DBG) Log.d(TAG, "Requesting refresh " + uri); 37994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney // finally, make the query 38094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney return context.getContentResolver().query(uri, null, null, null, null); 38194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 38294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 3833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean isWebSuggestionSource() { 384ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert return false; 3853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean queryAfterZeroResults() { 3883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.queryAfterZeroResults(); 3893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean shouldRewriteQueryFromData() { 3923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.shouldRewriteQueryFromData(); 3933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean shouldRewriteQueryFromText() { 3963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.shouldRewriteQueryFromText(); 3973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 400abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert public boolean equals(Object o) { 401abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert if (o != null && o.getClass().equals(this.getClass())) { 402abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert SearchableSource s = (SearchableSource) o; 403fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return s.getComponentName().equals(getComponentName()); 404abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert } 405abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert return false; 406abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert } 407abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert 408abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert @Override 409abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert public int hashCode() { 410fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getComponentName().hashCode(); 411abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert } 412abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert 413abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert @Override 4143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public String toString() { 415d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert return "SearchableSource{component=" + getFlattenedComponentName() + "}"; 4163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public String getDefaultIntentAction() { 4193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.getSuggestIntentAction(); 4203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public String getDefaultIntentData() { 4233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.getSuggestIntentData(); 4243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 426782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public String getSuggestActionMsg(int keyCode) { 427782dd228e78e9294692d639597f96c26283968bbBjorn Bringert SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); 428782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (actionKey == null) return null; 429782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return actionKey.getSuggestActionMsg(); 430782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 431782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 432782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public String getSuggestActionMsgColumn(int keyCode) { 433782dd228e78e9294692d639597f96c26283968bbBjorn Bringert SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); 434782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (actionKey == null) return null; 435782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return actionKey.getSuggestActionMsgColumn(); 436782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 437782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 438fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private CharSequence getText(int id) { 439fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (id == 0) return null; 440fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mContext.getPackageManager().getText(mActivityInfo.packageName, id, 441fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mActivityInfo.applicationInfo); 442fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 443fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 444fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private String getString(int id) { 445fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert CharSequence text = getText(id); 446fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return text == null ? null : text.toString(); 447fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 4483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert} 449