/* * Copyright (C) 2010 Florian Sundermann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import android.app.Activity; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcelable; import android.view.Window; public class AppWidgetPickActivity extends Activity { private Intent fIntent = null; private PackageManager fPManager = null; private AppWidgetManager fAppWManager = null; private ArrayList<SubItem> fItems; private int fAppWidgetId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setTitle(""); requestWindowFeature(Window.FEATURE_NO_TITLE); fIntent = getIntent(); final Intent intent = getIntent(); if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) { fAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); fPManager = getPackageManager(); fAppWManager = AppWidgetManager.getInstance(this); fItems = new ArrayList<SubItem>(); AddAppWidgetProviderInfos(); AddCustomAppWidgets(); Collections.sort(fItems, new Comparator<SubItem>() { @Override public int compare(SubItem object1, SubItem object2) { return object1.getName().compareToIgnoreCase(object2.getName()); } }); for(SubItem itm : fItems) { if (itm instanceof Item) { ((Item)itm).sort(); } } new PickWidgetDialog(this).showDialog(null); } else { finish(); } } public ArrayList<SubItem> getItems() { return fItems; } public void finishOk(SubItem item) { int result; if (item.getExtra() != null) { // If there are any extras, it's because this entry is custom. // Don't try to bind it, just pass it back to the app. setResult(RESULT_OK, getIntent(item)); } else { try { fAppWManager.bindAppWidgetId(fAppWidgetId, item.getProvider()); result = RESULT_OK; } catch (IllegalArgumentException e) { // This is thrown if they're already bound, or otherwise somehow // bogus. Set the result to canceled, and exit. The app *should* // clean up at this point. We could pass the error along, but // it's not clear that that's useful -- the widget will simply not // appear. result = RESULT_CANCELED; } setResult(result, fIntent); } finish(); } /** * Build the {@link Intent} described by this item. If this item * can't create a valid {@link ComponentName}, it will return * {@link Intent#ACTION_CREATE_SHORTCUT} filled with the item label. */ private Intent getIntent(SubItem itm) { Intent intent = null; Parcelable parcel = fIntent.getParcelableExtra(Intent.EXTRA_INTENT); if (parcel instanceof Intent) { intent = new Intent((Intent) parcel); } else { intent = new Intent(Intent.ACTION_MAIN, null); intent.addCategory(Intent.CATEGORY_DEFAULT); } if (itm.getProvider() != null) { // Valid package and class, so fill details as normal intent intent.setClassName(itm.getProvider().getPackageName(), itm.getProvider().getClassName()); } else { // No valid package or class, so treat as shortcut with label intent.setAction(Intent.ACTION_CREATE_SHORTCUT); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, itm.getName()); } if (itm.getExtra() != null) { intent.putExtras(itm.getExtra()); } return intent; } private Item getPackageItem(AppWidgetProviderInfo info) { String packName = info.provider.getPackageName(); for (SubItem itm : fItems) { if (itm instanceof Item) { Item i = (Item)itm; if (i.getPackageName().equals(packName)) { return i; } } } try { android.content.pm.ApplicationInfo appInfo = fPManager.getApplicationInfo(info.provider.getPackageName(), 0); Drawable appIcon = fPManager.getApplicationIcon(appInfo); CharSequence str = fPManager.getApplicationLabel(appInfo); Item newItm = new Item(str.toString(), appIcon); newItm.setPackageName(packName); fItems.add(newItm); return newItm; } catch(PackageManager.NameNotFoundException expt) { } return null; } private void AddAppWidgetProviderInfos() { List<AppWidgetProviderInfo> infos = fAppWManager.getInstalledProviders(); for(AppWidgetProviderInfo info : infos) { try { android.content.pm.ApplicationInfo appInfo = fPManager.getApplicationInfo(info.provider.getPackageName(), 0); SubItem itm = new SubItem(info.label, fPManager.getDrawable(info.provider.getPackageName(), info.icon, appInfo)); itm.setProvider(info.provider); Item mainItm = getPackageItem(info); mainItm.getItems().add(itm); } catch(PackageManager.NameNotFoundException expt) { } } } private void AddCustomAppWidgets() { final Bundle extras = fIntent.getExtras(); // get and validate the extras they gave us ArrayList<AppWidgetProviderInfo> customInfo = null; ArrayList<Bundle> customExtras = null; try_custom_items: { customInfo = extras.getParcelableArrayList(AppWidgetManager.EXTRA_CUSTOM_INFO); if (customInfo == null || customInfo.size() == 0) { break try_custom_items; } int customInfoSize = customInfo.size(); for (int i=0; i<customInfoSize; i++) { Parcelable p = customInfo.get(i); if (p == null || !(p instanceof AppWidgetProviderInfo)) { customInfo = null; break try_custom_items; } } customExtras = extras.getParcelableArrayList(AppWidgetManager.EXTRA_CUSTOM_EXTRAS); if (customExtras == null) { customInfo = null; break try_custom_items; } int customExtrasSize = customExtras.size(); if (customInfoSize != customExtrasSize) { break try_custom_items; } for (int i=0; i<customExtrasSize; i++) { Parcelable p = customExtras.get(i); if (p == null || !(p instanceof Bundle)) { customInfo = null; customExtras = null; break try_custom_items; } } } putAppWidgetItems(customInfo, customExtras); } private void putAppWidgetItems(List<AppWidgetProviderInfo> appWidgets, List<Bundle> customExtras) { if (appWidgets == null) return; final int size = appWidgets.size(); for (int i = 0; i < size; i++) { AppWidgetProviderInfo info = appWidgets.get(i); String label = info.label.toString(); Drawable icon = null; if (info.icon != 0) { icon = fPManager.getDrawable(info.provider.getPackageName(), info.icon, null); } Item item = new Item(label, icon); SubItem subItem = new SubItem(label, icon); item.getItems().add(subItem); item.setPackageName(info.provider.getPackageName()); if (customExtras != null) { subItem.setExtra(customExtras.get(i)); } fItems.add(item); } } }