2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings;
19 import android.appwidget.AppWidgetManager;
20 import android.appwidget.AppWidgetProviderInfo;
21 import android.content.DialogInterface;
22 import android.content.Intent;
23 import android.content.pm.PackageManager;
24 import android.graphics.drawable.Drawable;
25 import android.os.Bundle;
26 import android.os.Parcelable;
27 import android.util.Log;
29 import java.text.Collator;
30 import java.util.List;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.Comparator;
36 * Displays a list of {@link AppWidgetProviderInfo} widgets, along with any
37 * injected special widgets specified through
38 * {@link AppWidgetManager#EXTRA_CUSTOM_INFO} and
39 * {@link AppWidgetManager#EXTRA_CUSTOM_EXTRAS}.
41 * When an installed {@link AppWidgetProviderInfo} is selected, this activity
42 * will bind it to the given {@link AppWidgetManager#EXTRA_APPWIDGET_ID},
43 * otherwise it will return the requested extras.
45 public class AppWidgetPickActivity extends ActivityPicker {
46 private static final String TAG = "AppWidgetPickActivity";
47 private static final boolean LOGD = false;
49 private PackageManager mPackageManager;
50 private AppWidgetManager mAppWidgetManager;
53 * The allocated {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that this
54 * activity is binding.
56 private int mAppWidgetId;
59 public void onCreate(Bundle icicle) {
60 mPackageManager = getPackageManager();
61 mAppWidgetManager = AppWidgetManager.getInstance(this);
63 super.onCreate(icicle);
65 // Set default return data
66 setResultData(RESULT_CANCELED, null);
68 // Read the appWidgetId passed our direction, otherwise bail if not found
69 final Intent intent = getIntent();
70 if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
71 mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
72 AppWidgetManager.INVALID_APPWIDGET_ID);
79 * Create list entries for any custom widgets requested through
80 * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}.
82 void putCustomAppWidgets(List<PickAdapter.Item> items) {
83 final Bundle extras = getIntent().getExtras();
85 // get and validate the extras they gave us
86 ArrayList<AppWidgetProviderInfo> customInfo = null;
87 ArrayList<Bundle> customExtras = null;
89 customInfo = extras.getParcelableArrayList(AppWidgetManager.EXTRA_CUSTOM_INFO);
90 if (customInfo == null || customInfo.size() == 0) {
91 Log.i(TAG, "EXTRA_CUSTOM_INFO not present.");
92 break try_custom_items;
95 int customInfoSize = customInfo.size();
96 for (int i=0; i<customInfoSize; i++) {
97 Parcelable p = customInfo.get(i);
98 if (p == null || !(p instanceof AppWidgetProviderInfo)) {
100 Log.e(TAG, "error using EXTRA_CUSTOM_INFO index=" + i);
101 break try_custom_items;
105 customExtras = extras.getParcelableArrayList(AppWidgetManager.EXTRA_CUSTOM_EXTRAS);
106 if (customExtras == null) {
108 Log.e(TAG, "EXTRA_CUSTOM_INFO without EXTRA_CUSTOM_EXTRAS");
109 break try_custom_items;
112 int customExtrasSize = customExtras.size();
113 if (customInfoSize != customExtrasSize) {
114 Log.e(TAG, "list size mismatch: EXTRA_CUSTOM_INFO: " + customInfoSize
115 + " EXTRA_CUSTOM_EXTRAS: " + customExtrasSize);
116 break try_custom_items;
120 for (int i=0; i<customExtrasSize; i++) {
121 Parcelable p = customExtras.get(i);
122 if (p == null || !(p instanceof Bundle)) {
125 Log.e(TAG, "error using EXTRA_CUSTOM_EXTRAS index=" + i);
126 break try_custom_items;
131 if (LOGD) Log.d(TAG, "Using " + customInfo.size() + " custom items");
132 putAppWidgetItems(customInfo, customExtras, items);
139 public void onClick(DialogInterface dialog, int which) {
140 Intent intent = getIntentForPosition(which);
143 if (intent.getExtras() != null) {
144 // If there are any extras, it's because this entry is custom.
145 // Don't try to bind it, just pass it back to the app.
146 setResultData(RESULT_OK, intent);
149 mAppWidgetManager.bindAppWidgetId(mAppWidgetId, intent.getComponent());
151 } catch (IllegalArgumentException e) {
152 // This is thrown if they're already bound, or otherwise somehow
153 // bogus. Set the result to canceled, and exit. The app *should*
154 // clean up at this point. We could pass the error along, but
155 // it's not clear that that's useful -- the widget will simply not
157 result = RESULT_CANCELED;
159 setResultData(result, null);
165 * Create list entries for the given {@link AppWidgetProviderInfo} widgets,
166 * inserting extras if provided.
168 void putAppWidgetItems(List<AppWidgetProviderInfo> appWidgets,
169 List<Bundle> customExtras, List<PickAdapter.Item> items) {
170 if (appWidgets == null) return;
171 final int size = appWidgets.size();
172 for (int i = 0; i < size; i++) {
173 AppWidgetProviderInfo info = appWidgets.get(i);
175 CharSequence label = info.label;
176 Drawable icon = null;
178 if (info.icon != 0) {
179 icon = mPackageManager.getDrawable(info.provider.getPackageName(), info.icon, null);
181 Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon)
182 + " for provider: " + info.provider);
186 PickAdapter.Item item = new PickAdapter.Item(this, label, icon);
188 item.packageName = info.provider.getPackageName();
189 item.className = info.provider.getClassName();
191 if (customExtras != null) {
192 item.extras = customExtras.get(i);
200 * Build and return list of items to be shown in dialog. This will mix both
201 * installed {@link AppWidgetProviderInfo} and those provided through
202 * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}, sorting them alphabetically.
205 protected List<PickAdapter.Item> getItems() {
206 List<PickAdapter.Item> items = new ArrayList<PickAdapter.Item>();
208 putInstalledAppWidgets(items);
209 putCustomAppWidgets(items);
211 // Sort all items together by label
212 Collections.sort(items, new Comparator<PickAdapter.Item>() {
213 Collator mCollator = Collator.getInstance();
214 public int compare(PickAdapter.Item lhs, PickAdapter.Item rhs) {
215 return mCollator.compare(lhs.label, rhs.label);
223 * Create list entries for installed {@link AppWidgetProviderInfo} widgets.
225 void putInstalledAppWidgets(List<PickAdapter.Item> items) {
226 List<AppWidgetProviderInfo> installed = mAppWidgetManager.getInstalledProviders();
227 putAppWidgetItems(installed, null, items);
231 * Convenience method for setting the result code and intent. This method
232 * correctly injects the {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that
233 * most hosts expect returned.
235 void setResultData(int code, Intent intent) {
236 Intent result = intent != null ? intent : new Intent();
237 result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
238 setResult(code, result);