SearchWidgetProvider.java revision 970c3017a56be51401c4e5878d128c14f3bbf027
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.quicksearchbox; 18 19import android.app.PendingIntent; 20import android.app.SearchManager; 21import android.appwidget.AppWidgetManager; 22import android.appwidget.AppWidgetProvider; 23import android.content.ComponentName; 24import android.content.Context; 25import android.content.Intent; 26import android.net.Uri; 27import android.os.Bundle; 28import android.speech.RecognizerIntent; 29import android.util.Log; 30import android.view.KeyEvent; 31import android.view.View; 32import android.widget.RemoteViews; 33 34/** 35 * Search widget provider. 36 * 37 */ 38public class SearchWidgetProvider extends AppWidgetProvider { 39 40 private static final boolean DBG = true; 41 private static final String TAG = "QSB.SearchWidgetProvider"; 42 43 private static final boolean SHOW_SHORTCUT_IN_WIDGET = false; 44 45 private static final String ACTION_UPDATE_SEARCH_WIDGETS = 46 "com.android.quicksearchbox.UPDATE_SEARCH_WIDGETS"; 47 48 private static final String WIDGET_SEARCH_SOURCE = "launcher-search"; 49 private static final String WIDGET_SEARCH_SHORTCUT_SOURCE = "launcher-search-shortcut"; 50 51 // TODO: Expose SearchManager.SOURCE instead. 52 private static final String SOURCE = "source"; 53 54 /** 55 * Updates all search widgets. 56 */ 57 public static void updateSearchWidgets(Context context) { 58 Intent intent = new Intent(ACTION_UPDATE_SEARCH_WIDGETS); 59 intent.setComponent(myComponentName(context)); 60 if (DBG) Log.d(TAG, "Broadcasting " + intent); 61 context.sendBroadcast(intent); 62 } 63 64 /** 65 * Gets the component name for this app widget provider. 66 */ 67 private static ComponentName myComponentName(Context context) { 68 return new ComponentName(context, SearchWidgetProvider.class); 69 } 70 71 @Override 72 public void onReceive(Context context, Intent intent) { 73 String action = intent.getAction(); 74 if (ACTION_UPDATE_SEARCH_WIDGETS.equals(action)) { 75 // We requested the update. Find the widgets and update them. 76 AppWidgetManager manager = AppWidgetManager.getInstance(context); 77 int[] appWidgetIds = manager.getAppWidgetIds(myComponentName(context)); 78 onUpdate(context, manager, appWidgetIds); 79 } else { 80 // Handle actions requested by the widget host. 81 super.onReceive(context, intent); 82 } 83 } 84 85 @Override 86 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 87 updateSearchWidgets(context, appWidgetManager, appWidgetIds); 88 } 89 90 /** 91 * Updates a set of search widgets. 92 */ 93 private void updateSearchWidgets(Context context, AppWidgetManager appWidgetManager, 94 int[] appWidgetIds) { 95 if (DBG) Log.d(TAG, "updateSearchWidgets()"); 96 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.search_widget); 97 98 Bundle widgetAppData = new Bundle(); 99 widgetAppData.putString(SOURCE, WIDGET_SEARCH_SOURCE); 100 101 // Text field 102 Intent qsbIntent = new Intent(Intent.ACTION_MAIN); 103 qsbIntent.setClass(context, SearchActivity.class); 104 qsbIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 105 qsbIntent.putExtra(SearchManager.APP_DATA, widgetAppData); 106 PendingIntent textPendingIntent = PendingIntent.getActivity(context, 0, qsbIntent, 0); 107 views.setOnClickPendingIntent(R.id.search_widget_text, textPendingIntent); 108 109 // Voice search button. Only shown if voice search is available. 110 Intent voiceSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 111 voiceSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 112 voiceSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 113 RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH); 114 // TODO: Does VoiceSearch actually look at APP_DATA? 115 voiceSearchIntent.putExtra(SearchManager.APP_DATA, widgetAppData); 116 if (voiceSearchIntent.resolveActivity(context.getPackageManager()) != null) { 117 PendingIntent voicePendingIntent = 118 PendingIntent.getActivity(context, 0, voiceSearchIntent, 0); 119 views.setOnClickPendingIntent(R.id.search_widget_voice_btn, voicePendingIntent); 120 views.setViewVisibility(R.id.search_widget_voice_btn, View.VISIBLE); 121 } else { 122 views.setViewVisibility(R.id.search_widget_voice_btn, View.GONE); 123 } 124 125 // Shortcuts 126 if (SHOW_SHORTCUT_IN_WIDGET) { 127 bindShortcuts(context, views); 128 } 129 130 appWidgetManager.updateAppWidget(appWidgetIds, views); 131 } 132 133 private void bindShortcuts(Context context, RemoteViews views) { 134 ShortcutRepository shortcutRepo = getShortcutRepository(context); 135 SuggestionCursor shortcuts = shortcutRepo.getShortcutsForQuery(""); 136 try { 137 if (shortcuts != null && shortcuts.getCount() > 0) { 138 shortcuts.moveTo(0); 139 RemoteViews shortcutView = new RemoteViews(context.getPackageName(), 140 R.layout.widget_suggestion); 141 bindRemoteViewSuggestion(context, shortcutView, shortcuts); 142 views.addView(R.id.widget_shortcuts, shortcutView); 143 views.setViewVisibility(R.id.widget_shortcuts, View.VISIBLE); 144 } else { 145 if (DBG) Log.d(TAG, "No shortcuts, hiding drop-down."); 146 views.setViewVisibility(R.id.widget_shortcuts, View.GONE); 147 } 148 } finally { 149 if (shortcuts != null) { 150 shortcuts.close(); 151 } 152 } 153 } 154 155 private void bindRemoteViewSuggestion(Context context, RemoteViews views, 156 SuggestionCursor suggestion) { 157 CharSequence text1 = suggestion.getSuggestionFormattedText1(); 158 CharSequence text2 = suggestion.getSuggestionFormattedText2(); 159 Uri icon1 = suggestion.getIconUri(suggestion.getSuggestionIcon1()); 160 if (icon1 == null) { 161 icon1 = suggestion.getSourceIconUri(); 162 } 163 Uri icon2 = suggestion.getIconUri(suggestion.getSuggestionIcon2()); 164 PendingIntent pendingIntent = getWidgetSuggestionIntent(context, suggestion); 165 if (DBG) { 166 Log.d(TAG, "Adding shortcut to widget: text1=" + text1 + ",text2=" + text2 167 + ",icon1=" + icon1 + ",icon2=" + icon2); 168 Log.d(TAG, " intent=" + pendingIntent); 169 } 170 setText1(views, text1); 171 setIcon1(views, icon1); 172 setPendingIntent(views, pendingIntent); 173 } 174 175 private PendingIntent getWidgetSuggestionIntent(Context context, SuggestionCursor suggestion) { 176 Bundle widgetAppData = new Bundle(); 177 widgetAppData.putString(SOURCE, WIDGET_SEARCH_SHORTCUT_SOURCE); 178 Intent intent = suggestion.getSuggestionIntent(context, widgetAppData, 179 KeyEvent.KEYCODE_UNKNOWN, null); 180 return PendingIntent.getActivity(context, 0, intent, 0); 181 } 182 183 private void setText1(RemoteViews views, CharSequence text) { 184 views.setCharSequence(R.id.text1, "setText", text); 185 } 186 187 private void setIcon1(RemoteViews views, Uri icon) { 188 views.setImageViewUri(R.id.icon1, icon); 189 } 190 191 private void setPendingIntent(RemoteViews views, PendingIntent pendingIntent) { 192 views.setOnClickPendingIntent(R.id.widget_suggestion, pendingIntent); 193 } 194 195 private QsbApplication getQsbApplication(Context context) { 196 return (QsbApplication) context.getApplicationContext(); 197 } 198 199 private ShortcutRepository getShortcutRepository(Context context) { 200 return getQsbApplication(context).getShortcutRepository(); 201 } 202 203} 204