SearchWidgetProvider.java revision 6a8622297b91cd88304ff4890160528a55827b19
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 com.android.quicksearchbox.ui.SearchSourceSelector; 20import com.android.quicksearchbox.ui.SuggestionViewFactory; 21 22import android.app.PendingIntent; 23import android.app.SearchManager; 24import android.appwidget.AppWidgetManager; 25import android.appwidget.AppWidgetProvider; 26import android.content.ComponentName; 27import android.content.Context; 28import android.content.Intent; 29import android.net.Uri; 30import android.os.Bundle; 31import android.speech.RecognizerIntent; 32import android.util.Log; 33import android.view.KeyEvent; 34import android.view.View; 35import android.widget.RemoteViews; 36 37/** 38 * Search widget provider. 39 * 40 */ 41public class SearchWidgetProvider extends AppWidgetProvider { 42 43 private static final boolean DBG = true; 44 private static final String TAG = "QSB.SearchWidgetProvider"; 45 46 private static final boolean SHOW_SHORTCUT_IN_WIDGET = false; 47 48 private static final String ACTION_UPDATE_SEARCH_WIDGETS = 49 "com.android.quicksearchbox.UPDATE_SEARCH_WIDGETS"; 50 51 private static final String WIDGET_SEARCH_SOURCE = "launcher-search"; 52 private static final String WIDGET_SEARCH_SHORTCUT_SOURCE = "launcher-search-shortcut"; 53 54 // TODO: Expose SearchManager.SOURCE instead. 55 private static final String SOURCE = "source"; 56 57 /** 58 * Updates all search widgets. 59 */ 60 public static void updateSearchWidgets(Context context) { 61 Intent intent = new Intent(ACTION_UPDATE_SEARCH_WIDGETS); 62 intent.setPackage(context.getPackageName()); 63 if (DBG) Log.d(TAG, "Broadcasting " + intent); 64 context.sendBroadcast(intent); 65 } 66 67 @Override 68 public void onReceive(Context context, Intent intent) { 69 String action = intent.getAction(); 70 if (ACTION_UPDATE_SEARCH_WIDGETS.equals(action)) { 71 // We requested the update. Find the widgets and update them. 72 AppWidgetManager manager = AppWidgetManager.getInstance(context); 73 ComponentName self = new ComponentName(context, getClass()); 74 int[] appWidgetIds = manager.getAppWidgetIds(self); 75 onUpdate(context, manager, appWidgetIds); 76 } else { 77 // Handle actions requested by the widget host. 78 super.onReceive(context, intent); 79 } 80 } 81 82 @Override 83 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 84 updateSearchWidgets(context, appWidgetManager, appWidgetIds); 85 } 86 87 /** 88 * Updates a set of search widgets. 89 */ 90 private void updateSearchWidgets(Context context, AppWidgetManager appWidgetManager, 91 int[] appWidgetIds) { 92 if (DBG) Log.d(TAG, "updateSearchWidgets()"); 93 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.search_widget); 94 95 Bundle widgetAppData = new Bundle(); 96 widgetAppData.putString(SOURCE, WIDGET_SEARCH_SOURCE); 97 98 // Source selector 99 bindSourceSelector(context, views, widgetAppData); 100 101 // Text field 102 Intent qsbIntent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH); 103 qsbIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 104 qsbIntent.putExtra(SearchManager.APP_DATA, widgetAppData); 105 PendingIntent textPendingIntent = PendingIntent.getActivity(context, 0, qsbIntent, 0); 106 views.setOnClickPendingIntent(R.id.search_widget_text, textPendingIntent); 107 108 // Voice search button. Only shown if voice search is available. 109 Intent voiceSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 110 voiceSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 111 voiceSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 112 RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH); 113 // TODO: Does VoiceSearch actually look at APP_DATA? 114 voiceSearchIntent.putExtra(SearchManager.APP_DATA, widgetAppData); 115 if (voiceSearchIntent.resolveActivity(context.getPackageManager()) != null) { 116 PendingIntent voicePendingIntent = 117 PendingIntent.getActivity(context, 0, voiceSearchIntent, 0); 118 views.setOnClickPendingIntent(R.id.search_widget_voice_btn, voicePendingIntent); 119 views.setViewVisibility(R.id.search_widget_voice_btn, View.VISIBLE); 120 } else { 121 views.setViewVisibility(R.id.search_widget_voice_btn, View.GONE); 122 } 123 124 // Shortcuts 125 if (SHOW_SHORTCUT_IN_WIDGET) { 126 bindShortcuts(context, views); 127 } 128 129 appWidgetManager.updateAppWidget(appWidgetIds, views); 130 } 131 132 private void bindShortcuts(Context context, RemoteViews views) { 133 ShortcutRepository shortcutRepo = getShortcutRepository(context); 134 SuggestionCursor shortcuts = shortcutRepo.getShortcutsForQuery(""); 135 try { 136 if (shortcuts != null && shortcuts.getCount() > 0) { 137 shortcuts.moveTo(0); 138 RemoteViews shortcutView = new RemoteViews(context.getPackageName(), 139 R.layout.widget_suggestion); 140 bindRemoteViewSuggestion(context, shortcutView, shortcuts); 141 views.addView(R.id.widget_shortcuts, shortcutView); 142 views.setViewVisibility(R.id.widget_shortcuts, View.VISIBLE); 143 } else { 144 if (DBG) Log.d(TAG, "No shortcuts, hiding drop-down."); 145 views.setViewVisibility(R.id.widget_shortcuts, View.GONE); 146 } 147 } finally { 148 if (shortcuts != null) { 149 shortcuts.close(); 150 } 151 } 152 } 153 154 private void bindSourceSelector(Context context, RemoteViews views, Bundle widgetAppData) { 155 Source source = getSources(context).getLastSelectedSource(); 156 Uri sourceIconUri = getSourceIconUri(context, source); 157 views.setImageViewUri(SearchSourceSelector.ICON_VIEW_ID, sourceIconUri); 158 Intent intent = SearchSourceSelector.createIntent(null, "", widgetAppData); 159 PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); 160 views.setOnClickPendingIntent(SearchSourceSelector.ICON_VIEW_ID, pendingIntent); 161 } 162 163 private Uri getSourceIconUri(Context context, Source source) { 164 if (source == null) { 165 return getSuggestionViewFactory(context).getGlobalSearchIconUri(); 166 } 167 return source.getSourceIconUri(); 168 } 169 170 private void bindRemoteViewSuggestion(Context context, RemoteViews views, 171 SuggestionCursor suggestion) { 172 CharSequence text1 = suggestion.getSuggestionFormattedText1(); 173 CharSequence text2 = suggestion.getSuggestionFormattedText2(); 174 Uri icon1 = suggestion.getIconUri(suggestion.getSuggestionIcon1()); 175 if (icon1 == null) { 176 icon1 = suggestion.getSourceIconUri(); 177 } 178 Uri icon2 = suggestion.getIconUri(suggestion.getSuggestionIcon2()); 179 PendingIntent pendingIntent = getWidgetSuggestionIntent(context, suggestion); 180 if (DBG) { 181 Log.d(TAG, "Adding shortcut to widget: text1=" + text1 + ",text2=" + text2 182 + ",icon1=" + icon1 + ",icon2=" + icon2); 183 Log.d(TAG, " intent=" + pendingIntent); 184 } 185 setText1(views, text1); 186 setIcon1(views, icon1); 187 setPendingIntent(views, pendingIntent); 188 } 189 190 private PendingIntent getWidgetSuggestionIntent(Context context, SuggestionCursor suggestion) { 191 Bundle widgetAppData = new Bundle(); 192 widgetAppData.putString(SOURCE, WIDGET_SEARCH_SHORTCUT_SOURCE); 193 Intent intent = suggestion.getSuggestionIntent(context, widgetAppData, 194 KeyEvent.KEYCODE_UNKNOWN, null); 195 return PendingIntent.getActivity(context, 0, intent, 0); 196 } 197 198 private void setText1(RemoteViews views, CharSequence text) { 199 views.setCharSequence(R.id.text1, "setText", text); 200 } 201 202 private void setIcon1(RemoteViews views, Uri icon) { 203 views.setImageViewUri(R.id.icon1, icon); 204 } 205 206 private void setPendingIntent(RemoteViews views, PendingIntent pendingIntent) { 207 views.setOnClickPendingIntent(R.id.widget_suggestion, pendingIntent); 208 } 209 210 private QsbApplication getQsbApplication(Context context) { 211 return (QsbApplication) context.getApplicationContext(); 212 } 213 214 private SourceLookup getSources(Context context) { 215 return getQsbApplication(context).getSources(); 216 } 217 218 private ShortcutRepository getShortcutRepository(Context context) { 219 return getQsbApplication(context).getShortcutRepository(); 220 } 221 222 private SuggestionViewFactory getSuggestionViewFactory(Context context) { 223 return getQsbApplication(context).getSuggestionViewFactory(); 224 } 225 226} 227