SearchableSource.java revision 62adab88055fd0ef6779242245cdc8c3ae5f999c
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 5562adab88055fd0ef6779242245cdc8c3ae5f999cBjorn Bringert private final String mName; 5662adab88055fd0ef6779242245cdc8c3ae5f999cBjorn Bringert 573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private final ActivityInfo mActivityInfo; 583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Cached label for the activity 603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private CharSequence mLabel = null; 613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Cached icon for the activity 633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private Drawable.ConstantState mSourceIcon = null; 643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private final IconLoader mIconLoader; 663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public SearchableSource(Context context, SearchableInfo searchable) 683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert throws NameNotFoundException { 693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert ComponentName componentName = searchable.getSearchActivity(); 703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mContext = context; 713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSearchable = searchable; 7262adab88055fd0ef6779242245cdc8c3ae5f999cBjorn Bringert mName = componentName.flattenToShortString(); 733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mActivityInfo = context.getPackageManager().getActivityInfo(componentName, 0); 743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 75e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert mIconLoader = createIconLoader(context, searchable.getSuggestPackage()); 76e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert } 77e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert 78fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected Context getContext() { 79fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mContext; 80fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 81fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 82fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected SearchableInfo getSearchableInfo() { 83fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mSearchable; 84fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 85fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 86e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert private IconLoader createIconLoader(Context context, String providerPackage) { 87e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert if (providerPackage == null) return null; 88e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert try { 89e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert return new CachingIconLoader(new PackageIconLoader(context, providerPackage)); 90e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert } catch (PackageManager.NameNotFoundException ex) { 91e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert Log.e(TAG, "Suggestion provider package not found: " + providerPackage); 92e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert return null; 93e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert } 943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public ComponentName getComponentName() { 973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.getSearchActivity(); 983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 100f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert public String getName() { 10162adab88055fd0ef6779242245cdc8c3ae5f999cBjorn Bringert return mName; 102d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert } 103d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert 1043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public Drawable getIcon(String drawableId) { 105e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert return mIconLoader == null ? null : mIconLoader.getIcon(drawableId); 1063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public Uri getIconUri(String drawableId) { 109e1fc4581ebab65220a82bcdb3272b4eb85453837Bjorn Bringert return mIconLoader == null ? null : mIconLoader.getIconUri(drawableId); 1103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public CharSequence getLabel() { 1133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (mLabel == null) { 1143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Load label lazily 1153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mLabel = mActivityInfo.loadLabel(mContext.getPackageManager()); 1163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mLabel; 1183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1205691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert public CharSequence getHint() { 1215691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert return getText(mSearchable.getHintId()); 1225691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert } 1235691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert 1243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public int getQueryThreshold() { 1253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.getSuggestThreshold(); 1263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1288d9d845323514c34bb07d6eb91146a975324fcedBjorn Bringert public CharSequence getSettingsDescription() { 129fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return getText(mSearchable.getSettingsDescriptionId()); 1303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public Drawable getSourceIcon() { 1333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (mSourceIcon == null) { 1343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Load icon lazily 1353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert int iconRes = getSourceIconResource(); 1363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert PackageManager pm = mContext.getPackageManager(); 1373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Drawable icon = pm.getDrawable(mActivityInfo.packageName, iconRes, 1383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mActivityInfo.applicationInfo); 1393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Can't share Drawable instances, save constant state instead. 1403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSourceIcon = (icon != null) ? icon.getConstantState() : null; 1413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // Optimization, return the Drawable the first time 1423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return icon; 1433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return (mSourceIcon != null) ? mSourceIcon.newDrawable() : null; 1453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public Uri getSourceIconUri() { 148d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert int resourceId = getSourceIconResource(); 149d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert return new Uri.Builder() 150d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) 151d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert .authority(getComponentName().getPackageName()) 152d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert .appendEncodedPath(String.valueOf(resourceId)) 153d32d6753347e872aa5d9d6e9015ed7f24db3e362Bjorn Bringert .build(); 1543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 1563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private int getSourceIconResource() { 1573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert int icon = mActivityInfo.getIconResource(); 1583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return (icon != 0) ? icon : android.R.drawable.sym_def_app_icon; 1593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 161fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public boolean voiceSearchEnabled() { 162fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mSearchable.getVoiceSearchEnabled(); 163fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 164fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 165fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // TODO: not all apps handle ACTION_SEARCH properly, e.g. ApplicationsProvider. 166fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Maybe we should add a flag to searchable, so that QSB can hide the search button? 167fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public Intent createSearchIntent(String query, Bundle appData) { 168fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Intent intent = new Intent(Intent.ACTION_SEARCH); 169fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.setComponent(getComponentName()); 170fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 171fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // We need CLEAR_TOP to avoid reusing an old task that has other activities 172fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // on top of the one we want. 173fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 174fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.putExtra(SearchManager.USER_QUERY, query); 175fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.putExtra(SearchManager.QUERY, query); 176fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (appData != null) { 177fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert intent.putExtra(SearchManager.APP_DATA, appData); 178fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 179fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return intent; 180fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 181fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 182fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public Intent createVoiceSearchIntent(Bundle appData) { 183fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (mSearchable.getVoiceSearchLaunchWebSearch()) { 184fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return WebCorpus.createVoiceWebSearchIntent(appData); 185fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } else if (mSearchable.getVoiceSearchLaunchRecognizer()) { 186fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return createVoiceAppSearchIntent(appData); 187fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 188fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return null; 189fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 190fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 191fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert /** 192fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * Create and return an Intent that can launch the voice search activity, perform a specific 193fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * voice transcription, and forward the results to the searchable activity. 194fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * 195fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * This code is copied from SearchDialog 196fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * 197fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * @return A completely-configured intent ready to send to the voice search activity 198fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert */ 199fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private Intent createVoiceAppSearchIntent(Bundle appData) { 200fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert ComponentName searchActivity = mSearchable.getSearchActivity(); 201fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 202fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // create the necessary intent to set up a search-and-forward operation 203fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // in the voice search system. We have to keep the bundle separate, 204fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // because it becomes immutable once it enters the PendingIntent 205fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Intent queryIntent = new Intent(Intent.ACTION_SEARCH); 206fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert queryIntent.setComponent(searchActivity); 207fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert PendingIntent pending = PendingIntent.getActivity( 208fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert getContext(), 0, queryIntent, PendingIntent.FLAG_ONE_SHOT); 209fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 210fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Now set up the bundle that will be inserted into the pending intent 211fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // when it's time to do the search. We always build it here (even if empty) 212fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // because the voice search activity will always need to insert "QUERY" into 213fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // it anyway. 214fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Bundle queryExtras = new Bundle(); 215fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (appData != null) { 216fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert queryExtras.putBundle(SearchManager.APP_DATA, appData); 217fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 218fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 219fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Now build the intent to launch the voice search. Add all necessary 220fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // extras to launch the voice recognizer, and then all the necessary extras 221fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // to forward the results to the searchable activity 222fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert Intent voiceIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); 223fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 224fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 225fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Add all of the configuration options supplied by the searchable's metadata 226fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String languageModel = getString(mSearchable.getVoiceLanguageModeId()); 227fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (languageModel == null) { 228fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert languageModel = RecognizerIntent.LANGUAGE_MODEL_FREE_FORM; 229fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 230fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String prompt = getString(mSearchable.getVoicePromptTextId()); 231fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert String language = getString(mSearchable.getVoiceLanguageId()); 232fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert int maxResults = mSearchable.getVoiceMaxResults(); 233fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (maxResults <= 0) { 234fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert maxResults = 1; 235fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 236fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 237fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel); 238fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt); 239fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language); 240fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxResults); 241fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(EXTRA_CALLING_PACKAGE, 242fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert searchActivity == null ? null : searchActivity.toShortString()); 243fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 244fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert // Add the values that configure forwarding the results 245fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pending); 246fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT_BUNDLE, queryExtras); 247fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 248fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return voiceIntent; 249fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 250fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 251fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public SourceResult getSuggestions(String query, int queryLimit) { 2523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert try { 2533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Cursor cursor = getSuggestions(mContext, mSearchable, query, queryLimit); 2543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, toString() + "[" + query + "] returned."); 255fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return new CursorBackedSourceResult(query, cursor); 2563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } catch (RuntimeException ex) { 2573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Log.e(TAG, toString() + "[" + query + "] failed", ex); 258fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return new CursorBackedSourceResult(query); 2593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 26294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney public SuggestionCursor refreshShortcut(String shortcutId, String extraData) { 26394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney Cursor cursor = null; 26494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney try { 26594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney cursor = getValidationCursor(mContext, mSearchable, shortcutId, extraData); 26694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (DBG) Log.d(TAG, toString() + "[" + shortcutId + "] returned."); 26794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (cursor != null && cursor.getCount() > 0) { 26894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney cursor.moveToFirst(); 26994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 270fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return new CursorBackedSourceResult(null, cursor); 27194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } catch (RuntimeException ex) { 27294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney Log.e(TAG, toString() + "[" + shortcutId + "] failed", ex); 27394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (cursor != null) { 27494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney cursor.close(); 27594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 27694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney // TODO: Should we delete the shortcut even if the failure is temporary? 27794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney return null; 27894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 27994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 28094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 281fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private class CursorBackedSourceResult extends CursorBackedSuggestionCursor 282fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert implements SourceResult { 283fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 284fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public CursorBackedSourceResult(String userQuery) { 285fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert this(userQuery, null); 286fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 287fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 288fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public CursorBackedSourceResult(String userQuery, Cursor cursor) { 289fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert super(userQuery, cursor); 290fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 291fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 292fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public Source getSource() { 293fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return SearchableSource.this; 294fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 295fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 296fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert @Override 297fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public Source getSuggestionSource() { 298fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return SearchableSource.this; 299fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 300fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 301883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert public boolean isSuggestionShortcut() { 302883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert return false; 303883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert } 304883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert 305bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert @Override 306bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert public String toString() { 307bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert return SearchableSource.this + "[" + getUserQuery() + "]"; 308bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert } 309bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert 310fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 311fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 3123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 3133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * This is a copy of {@link SearchManager#getSuggestions(SearchableInfo, String)}. 3143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 3153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private static Cursor getSuggestions(Context context, SearchableInfo searchable, String query, 3163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert int queryLimit) { 3173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (searchable == null) { 3183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return null; 3193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String authority = searchable.getSuggestAuthority(); 3223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (authority == null) { 3233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return null; 3243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Uri.Builder uriBuilder = new Uri.Builder() 3273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert .scheme(ContentResolver.SCHEME_CONTENT) 3283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert .authority(authority); 3293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // if content path provided, insert it now 3313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert final String contentPath = searchable.getSuggestPath(); 3323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (contentPath != null) { 3333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert uriBuilder.appendEncodedPath(contentPath); 3343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // append standard suggestion query path 3373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY); 3383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // get the query selection, may be null 3403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String selection = searchable.getSuggestSelection(); 3413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // inject query, either as selection args or inline 3423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert String[] selArgs = null; 3433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (selection != null) { // use selection if provided 3443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert selArgs = new String[] { query }; 3453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } else { // no selection, use REST pattern 3463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert uriBuilder.appendPath(query); 3473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert uriBuilder.appendQueryParameter("limit", String.valueOf(queryLimit)); 3503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Uri uri = uriBuilder.build(); 3523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // finally, make the query 3543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) { 3553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert Log.d(TAG, "query(" + uri + ",null," + selection + "," 3563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert + Arrays.toString(selArgs) + ",null)"); 3573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return context.getContentResolver().query(uri, null, selection, selArgs, null); 3593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 36194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney private static Cursor getValidationCursor(Context context, SearchableInfo searchable, 36294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney String shortcutId, String extraData) { 36394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney String authority = searchable.getSuggestAuthority(); 36494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (authority == null) { 36594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney return null; 36694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 36794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 36894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney Uri.Builder uriBuilder = new Uri.Builder() 36994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney .scheme(ContentResolver.SCHEME_CONTENT) 37094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney .authority(authority); 37194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 37294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney // if content path provided, insert it now 37394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney final String contentPath = searchable.getSuggestPath(); 37494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (contentPath != null) { 37594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney uriBuilder.appendEncodedPath(contentPath); 37694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 37794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 37894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney // append the shortcut path and id 37994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_SHORTCUT); 38094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney uriBuilder.appendPath(shortcutId); 38194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 38294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney Uri uri = uriBuilder 38394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney .appendQueryParameter(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA, extraData) 38494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney .build(); 38594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 38694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney if (DBG) Log.d(TAG, "Requesting refresh " + uri); 38794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney // finally, make the query 38894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney return context.getContentResolver().query(uri, null, null, null, null); 38994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 39094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 3913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean isWebSuggestionSource() { 392ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert return false; 3933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean queryAfterZeroResults() { 3963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.queryAfterZeroResults(); 3973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean shouldRewriteQueryFromData() { 4003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.shouldRewriteQueryFromData(); 4013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4023e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public boolean shouldRewriteQueryFromText() { 4043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.shouldRewriteQueryFromText(); 4053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 408abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert public boolean equals(Object o) { 409abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert if (o != null && o.getClass().equals(this.getClass())) { 410abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert SearchableSource s = (SearchableSource) o; 41162adab88055fd0ef6779242245cdc8c3ae5f999cBjorn Bringert return s.mName.equals(mName); 412abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert } 413abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert return false; 414abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert } 415abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert 416abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert @Override 417abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert public int hashCode() { 41862adab88055fd0ef6779242245cdc8c3ae5f999cBjorn Bringert return mName.hashCode(); 419abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert } 420abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert 421abd33f7f8d8e56348a8a87bb9e7af491d83ee833Bjorn Bringert @Override 4223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public String toString() { 423f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert return "SearchableSource{component=" + getName() + "}"; 4243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public String getDefaultIntentAction() { 4273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.getSuggestIntentAction(); 4283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public String getDefaultIntentData() { 4313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSearchable.getSuggestIntentData(); 4323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 434782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public String getSuggestActionMsg(int keyCode) { 435782dd228e78e9294692d639597f96c26283968bbBjorn Bringert SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); 436782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (actionKey == null) return null; 437782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return actionKey.getSuggestActionMsg(); 438782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 439782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 440782dd228e78e9294692d639597f96c26283968bbBjorn Bringert public String getSuggestActionMsgColumn(int keyCode) { 441782dd228e78e9294692d639597f96c26283968bbBjorn Bringert SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); 442782dd228e78e9294692d639597f96c26283968bbBjorn Bringert if (actionKey == null) return null; 443782dd228e78e9294692d639597f96c26283968bbBjorn Bringert return actionKey.getSuggestActionMsgColumn(); 444782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 445782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 446fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private CharSequence getText(int id) { 447fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (id == 0) return null; 448fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return mContext.getPackageManager().getText(mActivityInfo.packageName, id, 449fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mActivityInfo.applicationInfo); 450fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 451fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 452fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private String getString(int id) { 453fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert CharSequence text = getText(id); 454fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert return text == null ? null : text.toString(); 455fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 4563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert} 457