SearchWidgetProvider.java revision e1f9f3068739f1e8c452c87f2fc1ebb7570d6fab
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 String ACTION_UPDATE_SEARCH_WIDGETS = 44 "com.android.quicksearchbox.UPDATE_SEARCH_WIDGETS"; 45 46 private static final String WIDGET_SEARCH_SOURCE = "launcher-search"; 47 private static final String WIDGET_SEARCH_SHORTCUT_SOURCE = "launcher-search-shortcut"; 48 49 // TODO: Expose SearchManager.SOURCE instead. 50 private static final String SOURCE = "source"; 51 52 /** 53 * Updates all search widgets. 54 */ 55 public static void updateSearchWidgets(Context context) { 56 Intent intent = new Intent(ACTION_UPDATE_SEARCH_WIDGETS); 57 intent.setComponent(myComponentName(context)); 58 if (DBG) Log.d(TAG, "Broadcasting " + intent); 59 context.sendBroadcast(intent); 60 } 61 62 /** 63 * Gets the component name for this app widget provider. 64 */ 65 private static ComponentName myComponentName(Context context) { 66 return new ComponentName(context, SearchWidgetProvider.class); 67 } 68 69 @Override 70 public void onReceive(Context context, Intent intent) { 71 String action = intent.getAction(); 72 if (ACTION_UPDATE_SEARCH_WIDGETS.equals(action)) { 73 // We requested the update. Find the widgets and update them. 74 AppWidgetManager manager = AppWidgetManager.getInstance(context); 75 int[] appWidgetIds = manager.getAppWidgetIds(myComponentName(context)); 76 onUpdate(context, manager, appWidgetIds); 77 } else { 78 // Handle actions requested by the widget host. 79 super.onReceive(context, intent); 80 } 81 } 82 83 @Override 84 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 85 updateSearchWidgets(context, appWidgetManager, appWidgetIds); 86 } 87 88 /** 89 * Updates a set of search widgets. 90 */ 91 private void updateSearchWidgets(Context context, AppWidgetManager appWidgetManager, 92 int[] appWidgetIds) { 93 if (DBG) Log.d(TAG, "updateSearchWidgets()"); 94 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.search_widget); 95 96 Bundle widgetAppData = new Bundle(); 97 widgetAppData.putString(SOURCE, WIDGET_SEARCH_SOURCE); 98 99 // Text field 100 Intent qsbIntent = new Intent(Intent.ACTION_MAIN); 101 qsbIntent.setClass(context, SearchActivity.class); 102 qsbIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 103 qsbIntent.putExtra(SearchManager.APP_DATA, widgetAppData); 104 PendingIntent textPendingIntent = PendingIntent.getActivity(context, 0, qsbIntent, 0); 105 views.setOnClickPendingIntent(R.id.search_widget_text, textPendingIntent); 106 107 // Voice search button. Only shown if voice search is available. 108 Intent voiceSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 109 voiceSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 110 voiceSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 111 RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH); 112 // TODO: Does VoiceSearch actually look at APP_DATA? 113 voiceSearchIntent.putExtra(SearchManager.APP_DATA, widgetAppData); 114 if (voiceSearchIntent.resolveActivity(context.getPackageManager()) != null) { 115 PendingIntent voicePendingIntent = 116 PendingIntent.getActivity(context, 0, voiceSearchIntent, 0); 117 views.setOnClickPendingIntent(R.id.search_widget_voice_btn, voicePendingIntent); 118 views.setViewVisibility(R.id.search_widget_voice_btn, View.VISIBLE); 119 } else { 120 views.setViewVisibility(R.id.search_widget_voice_btn, View.GONE); 121 } 122 123 // Show the top shortcut 124 ShortcutRepository shortcutRepo = getShortcutRepository(context); 125 SuggestionCursor shortcuts = shortcutRepo.getShortcutsForQuery(""); 126 try { 127 if (shortcuts != null && shortcuts.getCount() > 0) { 128 shortcuts.moveTo(0); 129 RemoteViews shortcutView = new RemoteViews(context.getPackageName(), 130 R.layout.widget_suggestion); 131 bindRemoteViewSuggestion(context, shortcutView, shortcuts); 132 views.addView(R.id.widget_shortcuts, shortcutView); 133 views.setViewVisibility(R.id.widget_shortcuts, View.VISIBLE); 134 } else { 135 if (DBG) Log.d(TAG, "No shortcuts, hiding drop-down."); 136 views.setViewVisibility(R.id.widget_shortcuts, View.GONE); 137 } 138 } finally { 139 if (shortcuts != null) { 140 shortcuts.close(); 141 } 142 } 143 144 appWidgetManager.updateAppWidget(appWidgetIds, views); 145 } 146 147 private void bindRemoteViewSuggestion(Context context, RemoteViews views, 148 SuggestionCursor suggestion) { 149 CharSequence text1 = suggestion.getSuggestionFormattedText1(); 150 CharSequence text2 = suggestion.getSuggestionFormattedText2(); 151 Uri icon1 = suggestion.getIconUri(suggestion.getSuggestionIcon1()); 152 if (icon1 == null) { 153 icon1 = suggestion.getSourceIconUri(); 154 } 155 Uri icon2 = suggestion.getIconUri(suggestion.getSuggestionIcon2()); 156 PendingIntent pendingIntent = getWidgetSuggestionIntent(context, suggestion); 157 if (DBG) { 158 Log.d(TAG, "Adding shortcut to widget: text1=" + text1 + ",text2=" + text2 159 + ",icon1=" + icon1 + ",icon2=" + icon2); 160 Log.d(TAG, " intent=" + pendingIntent); 161 } 162 setText1(views, text1); 163 setIcon1(views, icon1); 164 setPendingIntent(views, pendingIntent); 165 } 166 167 private PendingIntent getWidgetSuggestionIntent(Context context, SuggestionCursor suggestion) { 168 Bundle widgetAppData = new Bundle(); 169 widgetAppData.putString(SOURCE, WIDGET_SEARCH_SHORTCUT_SOURCE); 170 Intent intent = suggestion.getSuggestionIntent(context, widgetAppData, 171 KeyEvent.KEYCODE_UNKNOWN, null); 172 return PendingIntent.getActivity(context, 0, intent, 0); 173 } 174 175 private void setText1(RemoteViews views, CharSequence text) { 176 views.setCharSequence(R.id.text1, "setText", text); 177 } 178 179 private void setIcon1(RemoteViews views, Uri icon) { 180 views.setImageViewUri(R.id.icon1, icon); 181 } 182 183 private void setPendingIntent(RemoteViews views, PendingIntent pendingIntent) { 184 views.setOnClickPendingIntent(R.id.widget_suggestion, pendingIntent); 185 } 186 187 private QsbApplication getQsbApplication(Context context) { 188 return (QsbApplication) context.getApplicationContext(); 189 } 190 191 private ShortcutRepository getShortcutRepository(Context context) { 192 return getQsbApplication(context).getShortcutRepository(); 193 } 194 195} 196