The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 1 | /* |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 2 | * Copyright (C) 2009 The Android Open Source Project |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 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 | |
| 17 | package com.android.settings; |
| 18 | |
The Android Open Source Project | 80a7a1d | 2009-03-11 12:11:59 -0700 | [diff] [blame] | 19 | import android.appwidget.AppWidgetManager; |
| 20 | import android.appwidget.AppWidgetProviderInfo; |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 21 | import android.content.Context; |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 22 | import android.content.DialogInterface; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 23 | import android.content.Intent; |
| 24 | import android.content.pm.PackageManager; |
Michael Jurka | 16398c9 | 2012-09-24 17:30:17 -0700 | [diff] [blame] | 25 | import android.content.pm.PackageManager.NameNotFoundException; |
| 26 | import android.content.res.Resources; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 27 | import android.graphics.drawable.Drawable; |
| 28 | import android.os.Bundle; |
Michael Jurka | 16398c9 | 2012-09-24 17:30:17 -0700 | [diff] [blame] | 29 | import android.util.DisplayMetrics; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 30 | import android.util.Log; |
| 31 | |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 32 | import com.android.settings.ActivityPicker.PickAdapter; |
| 33 | |
Michael Jurka | 16398c9 | 2012-09-24 17:30:17 -0700 | [diff] [blame] | 34 | import java.util.List; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 35 | |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 36 | /** |
| 37 | * Displays a list of {@link AppWidgetProviderInfo} widgets, along with any |
| 38 | * injected special widgets specified through |
| 39 | * {@link AppWidgetManager#EXTRA_CUSTOM_INFO} and |
| 40 | * {@link AppWidgetManager#EXTRA_CUSTOM_EXTRAS}. |
| 41 | * <p> |
| 42 | * When an installed {@link AppWidgetProviderInfo} is selected, this activity |
| 43 | * will bind it to the given {@link AppWidgetManager#EXTRA_APPWIDGET_ID}, |
| 44 | * otherwise it will return the requested extras. |
| 45 | */ |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 46 | public class AppWidgetPickActivity extends ActivityPicker |
| 47 | implements AppWidgetLoader.ItemConstructor<PickAdapter.Item>{ |
The Android Open Source Project | 80a7a1d | 2009-03-11 12:11:59 -0700 | [diff] [blame] | 48 | private static final String TAG = "AppWidgetPickActivity"; |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 49 | static final boolean LOGD = false; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 50 | |
Michael Jurka | 16398c9 | 2012-09-24 17:30:17 -0700 | [diff] [blame] | 51 | List<PickAdapter.Item> mItems; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 52 | |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 53 | /** |
| 54 | * The allocated {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that this |
| 55 | * activity is binding. |
| 56 | */ |
| 57 | private int mAppWidgetId; |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 58 | private AppWidgetLoader<PickAdapter.Item> mAppWidgetLoader; |
| 59 | private AppWidgetManager mAppWidgetManager; |
| 60 | private PackageManager mPackageManager; |
Jim Miller | f8f6217 | 2012-09-17 21:02:25 -0700 | [diff] [blame] | 61 | |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 62 | @Override |
| 63 | public void onCreate(Bundle icicle) { |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 64 | mPackageManager = getPackageManager(); |
| 65 | mAppWidgetManager = AppWidgetManager.getInstance(this); |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 66 | mAppWidgetLoader = new AppWidgetLoader<PickAdapter.Item> |
| 67 | (this, mAppWidgetManager, this); |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 68 | |
| 69 | super.onCreate(icicle); |
| 70 | |
| 71 | // Set default return data |
| 72 | setResultData(RESULT_CANCELED, null); |
| 73 | |
| 74 | // Read the appWidgetId passed our direction, otherwise bail if not found |
| 75 | final Intent intent = getIntent(); |
| 76 | if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) { |
| 77 | mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, |
| 78 | AppWidgetManager.INVALID_APPWIDGET_ID); |
| 79 | } else { |
The Android Open Source Project | e6dd1fa | 2009-03-18 17:39:48 -0700 | [diff] [blame] | 80 | finish(); |
| 81 | } |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 82 | } |
Adam Cohen | 8291c08 | 2012-09-11 18:41:01 -0700 | [diff] [blame] | 83 | |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 84 | /** |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 85 | * Build and return list of items to be shown in dialog. This will mix both |
| 86 | * installed {@link AppWidgetProviderInfo} and those provided through |
| 87 | * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}, sorting them alphabetically. |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 88 | */ |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 89 | @Override |
| 90 | protected List<PickAdapter.Item> getItems() { |
| 91 | mItems = mAppWidgetLoader.getItems(getIntent()); |
| 92 | return mItems; |
| 93 | } |
The Android Open Source Project | e6dd1fa | 2009-03-18 17:39:48 -0700 | [diff] [blame] | 94 | |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 95 | @Override |
| 96 | public PickAdapter.Item createItem(Context context, AppWidgetProviderInfo info, Bundle extras) { |
| 97 | CharSequence label = info.label; |
| 98 | Drawable icon = null; |
| 99 | |
| 100 | if (info.icon != 0) { |
| 101 | try { |
| 102 | final Resources res = context.getResources(); |
| 103 | final int density = res.getDisplayMetrics().densityDpi; |
| 104 | int iconDensity; |
| 105 | switch (density) { |
| 106 | case DisplayMetrics.DENSITY_MEDIUM: |
| 107 | iconDensity = DisplayMetrics.DENSITY_LOW; |
| 108 | case DisplayMetrics.DENSITY_TV: |
| 109 | iconDensity = DisplayMetrics.DENSITY_MEDIUM; |
| 110 | case DisplayMetrics.DENSITY_HIGH: |
| 111 | iconDensity = DisplayMetrics.DENSITY_MEDIUM; |
| 112 | case DisplayMetrics.DENSITY_XHIGH: |
| 113 | iconDensity = DisplayMetrics.DENSITY_HIGH; |
| 114 | case DisplayMetrics.DENSITY_XXHIGH: |
| 115 | iconDensity = DisplayMetrics.DENSITY_XHIGH; |
| 116 | default: |
| 117 | // The density is some abnormal value. Return some other |
| 118 | // abnormal value that is a reasonable scaling of it. |
| 119 | iconDensity = (int)((density*0.75f)+.5f); |
The Android Open Source Project | e6dd1fa | 2009-03-18 17:39:48 -0700 | [diff] [blame] | 120 | } |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 121 | Resources packageResources = mPackageManager. |
| 122 | getResourcesForApplication(info.provider.getPackageName()); |
| 123 | icon = packageResources.getDrawableForDensity(info.icon, iconDensity); |
| 124 | } catch (NameNotFoundException e) { |
| 125 | Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) |
| 126 | + " for provider: " + info.provider); |
The Android Open Source Project | e6dd1fa | 2009-03-18 17:39:48 -0700 | [diff] [blame] | 127 | } |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 128 | if (icon == null) { |
| 129 | Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) |
| 130 | + " for provider: " + info.provider); |
The Android Open Source Project | e6dd1fa | 2009-03-18 17:39:48 -0700 | [diff] [blame] | 131 | } |
The Android Open Source Project | e6dd1fa | 2009-03-18 17:39:48 -0700 | [diff] [blame] | 132 | } |
| 133 | |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 134 | PickAdapter.Item item = new PickAdapter.Item(context, label, icon); |
| 135 | item.packageName = info.provider.getPackageName(); |
| 136 | item.className = info.provider.getClassName(); |
| 137 | item.extras = extras; |
| 138 | return item; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 139 | } |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 140 | |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 141 | /** |
| 142 | * {@inheritDoc} |
| 143 | */ |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 144 | @Override |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 145 | public void onClick(DialogInterface dialog, int which) { |
| 146 | Intent intent = getIntentForPosition(which); |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 147 | PickAdapter.Item item = mItems.get(which); |
Adam Cohen | 85d4b5f | 2012-09-24 13:15:14 -0700 | [diff] [blame] | 148 | |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 149 | int result; |
Michael Jurka | 16398c9 | 2012-09-24 17:30:17 -0700 | [diff] [blame] | 150 | if (item.extras != null) { |
Adam Cohen | 85d4b5f | 2012-09-24 13:15:14 -0700 | [diff] [blame] | 151 | // If these extras are present it's because this entry is custom. |
The Android Open Source Project | e6dd1fa | 2009-03-18 17:39:48 -0700 | [diff] [blame] | 152 | // Don't try to bind it, just pass it back to the app. |
| 153 | setResultData(RESULT_OK, intent); |
| 154 | } else { |
| 155 | try { |
Adam Cohen | 85d4b5f | 2012-09-24 13:15:14 -0700 | [diff] [blame] | 156 | Bundle options = null; |
| 157 | if (intent.getExtras() != null) { |
| 158 | options = intent.getExtras().getBundle( |
| 159 | AppWidgetManager.EXTRA_APPWIDGET_OPTIONS); |
| 160 | } |
| 161 | mAppWidgetManager.bindAppWidgetId(mAppWidgetId, intent.getComponent(), options); |
The Android Open Source Project | e6dd1fa | 2009-03-18 17:39:48 -0700 | [diff] [blame] | 162 | result = RESULT_OK; |
| 163 | } catch (IllegalArgumentException e) { |
| 164 | // This is thrown if they're already bound, or otherwise somehow |
| 165 | // bogus. Set the result to canceled, and exit. The app *should* |
| 166 | // clean up at this point. We could pass the error along, but |
| 167 | // it's not clear that that's useful -- the widget will simply not |
| 168 | // appear. |
| 169 | result = RESULT_CANCELED; |
| 170 | } |
| 171 | setResultData(result, null); |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 172 | } |
Michael Jurka | 0b2bd8d | 2012-10-30 15:32:27 -0700 | [diff] [blame] | 173 | |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 174 | finish(); |
| 175 | } |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 176 | |
Jeffrey Sharkey | 173545e | 2009-03-24 20:43:02 -0700 | [diff] [blame] | 177 | |
| 178 | /** |
| 179 | * Convenience method for setting the result code and intent. This method |
| 180 | * correctly injects the {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that |
| 181 | * most hosts expect returned. |
| 182 | */ |
The Android Open Source Project | e6dd1fa | 2009-03-18 17:39:48 -0700 | [diff] [blame] | 183 | void setResultData(int code, Intent intent) { |
| 184 | Intent result = intent != null ? intent : new Intent(); |
The Android Open Source Project | 80a7a1d | 2009-03-11 12:11:59 -0700 | [diff] [blame] | 185 | result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 186 | setResult(code, result); |
| 187 | } |
| 188 | } |