Merge "Import translations. DO NOT MERGE" into jb-mr1-dev
diff --git a/res/drawable-hdpi/appwidget_item_bg_normal.9.png b/res/drawable-hdpi/appwidget_item_bg_normal.9.png
index baff858..6fd0e6e 100644
--- a/res/drawable-hdpi/appwidget_item_bg_normal.9.png
+++ b/res/drawable-hdpi/appwidget_item_bg_normal.9.png
Binary files differ
diff --git a/res/drawable-hdpi/appwidget_item_bg_pressed.9.png b/res/drawable-hdpi/appwidget_item_bg_pressed.9.png
index 7ec33dd..0da4a1d 100644
--- a/res/drawable-hdpi/appwidget_item_bg_pressed.9.png
+++ b/res/drawable-hdpi/appwidget_item_bg_pressed.9.png
Binary files differ
diff --git a/res/drawable-mdpi/appwidget_item_bg_normal.9.png b/res/drawable-mdpi/appwidget_item_bg_normal.9.png
index 976083f..47009b4 100644
--- a/res/drawable-mdpi/appwidget_item_bg_normal.9.png
+++ b/res/drawable-mdpi/appwidget_item_bg_normal.9.png
Binary files differ
diff --git a/res/drawable-mdpi/appwidget_item_bg_pressed.9.png b/res/drawable-mdpi/appwidget_item_bg_pressed.9.png
index 8f340d3..9a5001b 100644
--- a/res/drawable-mdpi/appwidget_item_bg_pressed.9.png
+++ b/res/drawable-mdpi/appwidget_item_bg_pressed.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/appwidget_item_bg_normal.9.png b/res/drawable-xhdpi/appwidget_item_bg_normal.9.png
index b26f1d2..3cb534a 100644
--- a/res/drawable-xhdpi/appwidget_item_bg_normal.9.png
+++ b/res/drawable-xhdpi/appwidget_item_bg_normal.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/appwidget_item_bg_pressed.9.png b/res/drawable-xhdpi/appwidget_item_bg_pressed.9.png
index 3871689..3160e85 100644
--- a/res/drawable-xhdpi/appwidget_item_bg_pressed.9.png
+++ b/res/drawable-xhdpi/appwidget_item_bg_pressed.9.png
Binary files differ
diff --git a/res/layout/keyguard_appwidget_item.xml b/res/layout/keyguard_appwidget_item.xml
index 7280098..de0c855 100755
--- a/res/layout/keyguard_appwidget_item.xml
+++ b/res/layout/keyguard_appwidget_item.xml
@@ -15,21 +15,33 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <LinearLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:id="@+id/icon_and_label"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="8dip"
- android:layout_marginRight="8dip"
- android:layout_marginTop="4dip"
- android:layout_marginBottom="4dip"
- android:background="@drawable/appwidget_item_bg"
- android:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:gravity="center_vertical"
- android:drawablePadding="8dip"
- android:paddingStart="11dip"
- android:paddingEnd="11dip" />
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:background="@drawable/appwidget_item_bg"
+ android:layout_marginTop="2dip"
+ android:layout_marginBottom="2dip"
+ android:layout_marginLeft="2dip"
+ android:layout_marginRight="2dip"
+ android:paddingLeft="16dip"
+ android:paddingRight="16dip"
+ android:paddingTop="16dip"
+ android:paddingBottom="16dip" >
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="@dimen/appwidget_preview_width"
+ android:layout_height="@dimen/appwidget_preview_height"
+ android:scaleType="center" />
+ <TextView
+ android:id="@+id/label"
+ style="@style/KeyguardAppWidgetItem"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="24dip"
+ android:paddingBottom="8dip"
+ android:gravity="left|bottom" />
+ </LinearLayout>
</FrameLayout>
diff --git a/res/layout/keyguard_appwidget_pick_layout.xml b/res/layout/keyguard_appwidget_picker_layout.xml
similarity index 76%
rename from res/layout/keyguard_appwidget_pick_layout.xml
rename to res/layout/keyguard_appwidget_picker_layout.xml
index feb85a5..b678925 100644
--- a/res/layout/keyguard_appwidget_pick_layout.xml
+++ b/res/layout/keyguard_appwidget_picker_layout.xml
@@ -18,10 +18,16 @@
android:id="@+id/layout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:layout_marginLeft="@dimen/keyguard_appwidget_picker_margin_left"
+ android:layout_marginRight="@dimen/keyguard_appwidget_picker_margin_right"
+ android:paddingTop="2dip"
+ android:paddingBottom="2dip"
android:orientation="vertical" >
<GridView android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
+ android:numColumns="@integer/keyguard_appwidget_picker_cols"
+ android:layout_gravity="center_horizontal"
android:listSelector="@android:color/transparent"
android:id="@+id/widget_list" />
</LinearLayout>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 2ced533..498aa4d 100755
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -17,4 +17,9 @@
<resources>
<dimen name="appwidget_width">421dip</dimen>
<dimen name="appwidget_height">68dip</dimen>
+ <dimen name="appwidget_preview_width">120dip</dimen>
+ <dimen name="appwidget_preview_height">70dip</dimen>
+ <dimen name="keyguard_appwidget_picker_margin_left">2dip</dimen>
+ <dimen name="keyguard_appwidget_picker_margin_right">2dip</dimen>
+ <integer name="keyguard_appwidget_picker_cols">2</integer>
</resources>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
new file mode 100644
index 0000000..0903167
--- /dev/null
+++ b/res/values-land/styles.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ 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.
+-->
+
+<resources>
+ <style name="KeyguardAppWidgetItem">
+ <item name="android:textSize">16sp</item>
+ </style>
+</resources>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
index 994d4bb..c0a79ad 100755
--- a/res/values-sw600dp-land/dimens.xml
+++ b/res/values-sw600dp-land/dimens.xml
@@ -18,4 +18,6 @@
<dimen name="screen_margin_sides">128dip</dimen>
<dimen name="screen_margin_top">72dip</dimen>
<dimen name="screen_margin_bottom">48dip</dimen>
+ <dimen name="appwidget_preview_height">80dip</dimen>
+ <dimen name="keyguard_appwidget_picker_width">720dip</dimen>
</resources>
diff --git a/res/values-sw600dp-land/styles.xml b/res/values-sw600dp-land/styles.xml
new file mode 100644
index 0000000..645d1fe
--- /dev/null
+++ b/res/values-sw600dp-land/styles.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ 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.
+-->
+
+<resources>
+ <style name="KeyguardAppWidgetItem">
+ <item name="android:textSize">18sp</item>
+ </style>
+</resources>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index cf7ac6b..1374efd 100755
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -32,4 +32,10 @@
<dimen name="setup_item_margin">32dip</dimen>
<dimen name="appwidget_min_width">325dip</dimen>
<dimen name="appwidget_min_height">50dip</dimen>
+
+ <dimen name="appwidget_preview_width">120dip</dimen>
+ <dimen name="appwidget_preview_height">70dip</dimen>
+ <dimen name="keyguard_appwidget_picker_margin_left">2dip</dimen>
+ <dimen name="keyguard_appwidget_picker_margin_right">2dip</dimen>
+ <integer name="keyguard_appwidget_picker_cols">2</integer>
</resources>
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
index f780f53..9f02164 100644
--- a/res/values-sw600dp/styles.xml
+++ b/res/values-sw600dp/styles.xml
@@ -57,4 +57,8 @@
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
<item name="android:textSize">20sp</item>
</style>
+
+ <style name="KeyguardAppWidgetItem">
+ <item name="android:textSize">16sp</item>
+ </style>
</resources>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 5a58609..d6d9184 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -16,4 +16,7 @@
<resources>
<dimen name="pager_tabs_padding">@*android:dimen/preference_fragment_padding_side</dimen>
+ <dimen name="appwidget_preview_height">80dip</dimen>
+ <integer name="keyguard_appwidget_picker_cols">2</integer>
+ <dimen name="keyguard_appwidget_picker_width">720dip</dimen>
</resources>
diff --git a/res/values-sw720dp/styles.xml b/res/values-sw720dp/styles.xml
new file mode 100644
index 0000000..645d1fe
--- /dev/null
+++ b/res/values-sw720dp/styles.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ 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.
+-->
+
+<resources>
+ <style name="KeyguardAppWidgetItem">
+ <item name="android:textSize">18sp</item>
+ </style>
+</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 34b2d86..91f293c 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -54,4 +54,11 @@
<dimen name="pager_tabs_padding">0dp</dimen>
+ <!-- Size of AppWidget previews in KeyguardAppWidgetPickActivity -->
+ <dimen name="appwidget_preview_width">140dip</dimen>
+ <dimen name="appwidget_preview_height">80dip</dimen>
+ <dimen name="keyguard_appwidget_picker_max_width">800dip</dimen>
+ <dimen name="keyguard_appwidget_picker_margin_left">6dip</dimen>
+ <dimen name="keyguard_appwidget_picker_margin_right">6dip</dimen>
+ <integer name="keyguard_appwidget_picker_cols">1</integer>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 9b9cb83..dda22d9 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -191,4 +191,8 @@
<item name="android:textAllCaps">true</item>
<item name="android:textStyle">bold</item>
</style>
+
+ <style name="KeyguardAppWidgetItem">
+ <item name="android:textSize">18sp</item>
+ </style>
</resources>
diff --git a/src/com/android/settings/KeyguardAppWidgetPickActivity.java b/src/com/android/settings/KeyguardAppWidgetPickActivity.java
index 0afc5b2..db5f115 100644
--- a/src/com/android/settings/KeyguardAppWidgetPickActivity.java
+++ b/src/com/android/settings/KeyguardAppWidgetPickActivity.java
@@ -17,26 +17,24 @@
package com.android.settings;
import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.LauncherActivity.IconResizer;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
-import android.graphics.ColorFilter;
import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
-import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.PaintDrawable;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
@@ -50,11 +48,13 @@
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
+import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.widget.LockPatternUtils;
+import java.lang.ref.WeakReference;
import java.util.List;
/**
@@ -77,17 +77,18 @@
private AppWidgetLoader<Item> mAppWidgetLoader;
private List<Item> mItems;
private GridView mGridView;
+ private AppWidgetAdapter mAppWidgetAdapter;
private AppWidgetManager mAppWidgetManager;
private int mAppWidgetId;
// Might make it possible to make this be false in future
private boolean mAddingToKeyguard = true;
private Intent mResultData;
private LockPatternUtils mLockPatternUtils;
- private boolean mSuccess;
+ private Bundle mExtraConfigureOptions;
@Override
protected void onCreate(Bundle savedInstanceState) {
- setContentView(R.layout.keyguard_appwidget_pick_layout);
+ setContentView(R.layout.keyguard_appwidget_picker_layout);
super.onCreate(savedInstanceState);
// Set default return data
@@ -101,13 +102,22 @@
} else {
finish();
}
+ mExtraConfigureOptions = intent.getBundleExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);
mGridView = (GridView) findViewById(R.id.widget_list);
+ DisplayMetrics dm = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(dm);
+ int maxGridWidth = getResources().getDimensionPixelSize(
+ R.dimen.keyguard_appwidget_picker_max_width);
+
+ if (maxGridWidth < dm.widthPixels) {
+ mGridView.getLayoutParams().width = maxGridWidth;
+ }
mAppWidgetManager = AppWidgetManager.getInstance(this);
mAppWidgetLoader = new AppWidgetLoader<Item>(this, mAppWidgetManager, this);
mItems = mAppWidgetLoader.getItems(getIntent());
- AppWidgetAdapter adapter = new AppWidgetAdapter(this, mItems);
- mGridView.setAdapter(adapter);
+ mAppWidgetAdapter = new AppWidgetAdapter(this, mItems);
+ mGridView.setAdapter(mAppWidgetAdapter);
mGridView.setOnItemClickListener(this);
mLockPatternUtils = new LockPatternUtils(this); // TEMP-- we want to delete this
@@ -125,207 +135,40 @@
setResult(code, result);
}
- private static class EmptyDrawable extends Drawable {
- private final int mWidth;
- private final int mHeight;
-
- EmptyDrawable(int width, int height) {
- mWidth = width;
- mHeight = height;
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mWidth;
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mHeight;
- }
-
- @Override
- public int getMinimumWidth() {
- return mWidth;
- }
-
- @Override
- public int getMinimumHeight() {
- return mHeight;
- }
-
- @Override
- public void draw(Canvas canvas) {
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
- }
-
- /**
- * Utility class to resize icons to match default icon size. Code is mostly
- * borrowed from Launcher.
- */
- private static class IconResizer {
- private final int mIconWidth;
- private final int mIconHeight;
-
- private final DisplayMetrics mMetrics;
- private final Rect mOldBounds = new Rect();
- private final Canvas mCanvas = new Canvas();
-
- public IconResizer(int width, int height, DisplayMetrics metrics) {
- mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
- Paint.FILTER_BITMAP_FLAG));
-
- mMetrics = metrics;
- mIconWidth = width;
- mIconHeight = height;
- }
-
- /**
- * Returns a Drawable representing the thumbnail of the specified Drawable.
- * The size of the thumbnail is defined by the dimension
- * android.R.dimen.launcher_application_icon_size.
- *
- * This method is not thread-safe and should be invoked on the UI thread only.
- *
- * @param icon The icon to get a thumbnail of.
- *
- * @return A thumbnail for the specified icon or the icon itself if the
- * thumbnail could not be created.
- */
- public Drawable createIconThumbnail(Drawable icon) {
- int width = mIconWidth;
- int height = mIconHeight;
-
- if (icon == null) {
- return new EmptyDrawable(width, height);
- }
-
- try {
- if (icon instanceof PaintDrawable) {
- PaintDrawable painter = (PaintDrawable) icon;
- painter.setIntrinsicWidth(width);
- painter.setIntrinsicHeight(height);
- } else if (icon instanceof BitmapDrawable) {
- // Ensure the bitmap has a density.
- BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
- Bitmap bitmap = bitmapDrawable.getBitmap();
- if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
- bitmapDrawable.setTargetDensity(mMetrics);
- }
- }
- int iconWidth = icon.getIntrinsicWidth();
- int iconHeight = icon.getIntrinsicHeight();
-
- if (iconWidth > 0 && iconHeight > 0) {
- if (width < iconWidth || height < iconHeight) {
- final float ratio = (float) iconWidth / iconHeight;
-
- if (iconWidth > iconHeight) {
- height = (int) (width / ratio);
- } else if (iconHeight > iconWidth) {
- width = (int) (height * ratio);
- }
-
- final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
- Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
- final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
- final Canvas canvas = mCanvas;
- canvas.setBitmap(thumb);
- // Copy the old bounds to restore them later
- // If we were to do oldBounds = icon.getBounds(),
- // the call to setBounds() that follows would
- // change the same instance and we would lose the
- // old bounds
- mOldBounds.set(icon.getBounds());
- final int x = (mIconWidth - width) / 2;
- final int y = (mIconHeight - height) / 2;
- icon.setBounds(x, y, x + width, y + height);
- icon.draw(canvas);
- icon.setBounds(mOldBounds);
- //noinspection deprecation
- icon = new BitmapDrawable(thumb);
- ((BitmapDrawable) icon).setTargetDensity(mMetrics);
- canvas.setBitmap(null);
- } else if (iconWidth < width && iconHeight < height) {
- final Bitmap.Config c = Bitmap.Config.ARGB_8888;
- final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
- final Canvas canvas = mCanvas;
- canvas.setBitmap(thumb);
- mOldBounds.set(icon.getBounds());
- final int x = (width - iconWidth) / 2;
- final int y = (height - iconHeight) / 2;
- icon.setBounds(x, y, x + iconWidth, y + iconHeight);
- icon.draw(canvas);
- icon.setBounds(mOldBounds);
- //noinspection deprecation
- icon = new BitmapDrawable(thumb);
- ((BitmapDrawable) icon).setTargetDensity(mMetrics);
- canvas.setBitmap(null);
- }
- }
-
- } catch (Throwable t) {
- icon = new EmptyDrawable(width, height);
- }
-
- return icon;
- }
- }
-
/**
* Item that appears in the AppWidget picker grid.
*/
public static class Item implements AppWidgetLoader.LabelledItem {
protected static IconResizer sResizer;
- protected IconResizer getResizer(Context context) {
- if (sResizer == null) {
- final Resources resources = context.getResources();
- int size = (int) resources.getDimension(android.R.dimen.app_icon_size);
- sResizer = new IconResizer(size, size, resources.getDisplayMetrics());
- }
- return sResizer;
- }
+
CharSequence label;
- Drawable icon;
+ int appWidgetPreviewId;
+ int iconId;
String packageName;
String className;
Bundle extras;
+ private WidgetPreviewLoader mWidgetPreviewLoader;
+ private Context mContext;
/**
* Create a list item from given label and icon.
*/
- Item(Context context, CharSequence label, Drawable icon) {
+ Item(Context context, CharSequence label) {
this.label = label;
- this.icon = getResizer(context).createIconThumbnail(icon);
+ mContext = context;
}
- /**
- * Create a list item and fill it with details from the given
- * {@link ResolveInfo} object.
- */
- Item(Context context, PackageManager pm, ResolveInfo resolveInfo) {
- label = resolveInfo.loadLabel(pm);
- if (label == null && resolveInfo.activityInfo != null) {
- label = resolveInfo.activityInfo.name;
- }
+ void loadWidgetPreview(ImageView v) {
+ mWidgetPreviewLoader = new WidgetPreviewLoader(mContext, v);
+ mWidgetPreviewLoader.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }
- icon = getResizer(context).createIconThumbnail(resolveInfo.loadIcon(pm));
- packageName = resolveInfo.activityInfo.applicationInfo.packageName;
- className = resolveInfo.activityInfo.name;
+ void cancelLoadingWidgetPreview() {
+ if (mWidgetPreviewLoader != null) {
+ mWidgetPreviewLoader.cancel(false);
+ mWidgetPreviewLoader = null;
+ }
}
/**
@@ -352,48 +195,259 @@
public CharSequence getLabel() {
return label;
}
+
+ class WidgetPreviewLoader extends AsyncTask<Void, Bitmap, Void> {
+ private Resources mResources;
+ private PackageManager mPackageManager;
+ private int mIconDpi;
+ private ImageView mView;
+ public WidgetPreviewLoader(Context context, ImageView v) {
+ super();
+ mResources = context.getResources();
+ mPackageManager = context.getPackageManager();
+ ActivityManager activityManager =
+ (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ mIconDpi = activityManager.getLauncherLargeIconDensity();
+ mView = v;
+ }
+ public Void doInBackground(Void... params) {
+ if (!isCancelled()) {
+ int appWidgetPreviewWidth =
+ mResources.getDimensionPixelSize(R.dimen.appwidget_preview_width);
+ int appWidgetPreviewHeight =
+ mResources.getDimensionPixelSize(R.dimen.appwidget_preview_height);
+ // TODO: fix the hspan, vspan of the default preview
+ Bitmap b = getWidgetPreview(new ComponentName(packageName, className),
+ appWidgetPreviewId, iconId,
+ appWidgetPreviewWidth, appWidgetPreviewHeight);
+ publishProgress(b);
+ }
+ return null;
+ }
+ public void onProgressUpdate(Bitmap... values) {
+ if (!isCancelled()) {
+ Bitmap b = values[0];
+ mView.setImageBitmap(b);
+ }
+ }
+ abstract class WeakReferenceThreadLocal<T> {
+ private ThreadLocal<WeakReference<T>> mThreadLocal;
+ public WeakReferenceThreadLocal() {
+ mThreadLocal = new ThreadLocal<WeakReference<T>>();
+ }
+
+ abstract T initialValue();
+
+ public void set(T t) {
+ mThreadLocal.set(new WeakReference<T>(t));
+ }
+
+ public T get() {
+ WeakReference<T> reference = mThreadLocal.get();
+ T obj;
+ if (reference == null) {
+ obj = initialValue();
+ mThreadLocal.set(new WeakReference<T>(obj));
+ return obj;
+ } else {
+ obj = reference.get();
+ if (obj == null) {
+ obj = initialValue();
+ mThreadLocal.set(new WeakReference<T>(obj));
+ }
+ return obj;
+ }
+ }
+ }
+
+ class CanvasCache extends WeakReferenceThreadLocal<Canvas> {
+ @Override
+ protected Canvas initialValue() {
+ return new Canvas();
+ }
+ }
+
+ class PaintCache extends WeakReferenceThreadLocal<Paint> {
+ @Override
+ protected Paint initialValue() {
+ return null;
+ }
+ }
+
+ class BitmapCache extends WeakReferenceThreadLocal<Bitmap> {
+ @Override
+ protected Bitmap initialValue() {
+ return null;
+ }
+ }
+
+ class RectCache extends WeakReferenceThreadLocal<Rect> {
+ @Override
+ protected Rect initialValue() {
+ return new Rect();
+ }
+ }
+
+ // Used for drawing widget previews
+ CanvasCache sCachedAppWidgetPreviewCanvas = new CanvasCache();
+ RectCache sCachedAppWidgetPreviewSrcRect = new RectCache();
+ RectCache sCachedAppWidgetPreviewDestRect = new RectCache();
+ PaintCache sCachedAppWidgetPreviewPaint = new PaintCache();
+
+ private Bitmap getWidgetPreview(ComponentName provider, int previewImage,
+ int iconId, int maxWidth, int maxHeight) {
+ // Load the preview image if possible
+ String packageName = provider.getPackageName();
+ if (maxWidth < 0) maxWidth = Integer.MAX_VALUE;
+ if (maxHeight < 0) maxHeight = Integer.MAX_VALUE;
+
+
+ int appIconSize = mResources.getDimensionPixelSize(R.dimen.app_icon_size);
+
+ Drawable drawable = null;
+ if (previewImage != 0) {
+ drawable = mPackageManager.getDrawable(packageName, previewImage, null);
+ if (drawable == null) {
+ Log.w(TAG, "Can't load widget preview drawable 0x" +
+ Integer.toHexString(previewImage) + " for provider: " + provider);
+ }
+ }
+
+ int bitmapWidth;
+ int bitmapHeight;
+ Bitmap defaultPreview = null;
+ boolean widgetPreviewExists = (drawable != null);
+ if (widgetPreviewExists) {
+ bitmapWidth = drawable.getIntrinsicWidth();
+ bitmapHeight = drawable.getIntrinsicHeight();
+ } else {
+ // Generate a preview image if we couldn't load one
+ bitmapWidth = maxWidth;
+ bitmapHeight = maxHeight;
+ defaultPreview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
+ Config.ARGB_8888);
+ final Canvas c = sCachedAppWidgetPreviewCanvas.get();
+ c.setBitmap(defaultPreview);
+ c.drawColor(0xFF2D2D2D);
+ c.setBitmap(null);
+
+ // Draw the icon in the top left corner
+ final float marginPercentage = 0.125f;
+ final float finalIconSize = (bitmapHeight / 2);
+ float iconScale = finalIconSize / appIconSize;
+
+ try {
+ Drawable icon = null;
+ int hoffset =
+ (int) (finalIconSize * marginPercentage);
+ int yoffset =
+ (int) (finalIconSize * marginPercentage);
+ if (iconId > 0)
+ icon = getFullResIcon(packageName, iconId);
+ if (icon != null) {
+ renderDrawableToBitmap(icon, defaultPreview, hoffset,
+ yoffset, (int) (appIconSize * iconScale),
+ (int) (appIconSize * iconScale));
+ }
+ } catch (Resources.NotFoundException e) {
+ }
+ }
+
+ // Scale to fit width only - let the widget preview be clipped in the
+ // vertical dimension
+ float scale = 1f;
+ if (bitmapWidth > maxWidth) {
+ scale = maxWidth / (float) bitmapWidth;
+ }
+ int finalPreviewWidth = (int) (scale * bitmapWidth);
+ int finalPreviewHeight = (int) (scale * bitmapHeight);
+
+ bitmapWidth = finalPreviewWidth;
+ bitmapHeight = Math.min(finalPreviewHeight, maxHeight);
+
+ Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
+ Config.ARGB_8888);
+
+ // Draw the scaled preview into the final bitmap
+ if (widgetPreviewExists) {
+ renderDrawableToBitmap(drawable, preview, 0, 0, finalPreviewWidth,
+ finalPreviewHeight);
+ } else {
+ final Canvas c = sCachedAppWidgetPreviewCanvas.get();
+ final Rect src = sCachedAppWidgetPreviewSrcRect.get();
+ final Rect dest = sCachedAppWidgetPreviewDestRect.get();
+ c.setBitmap(preview);
+ src.set(0, 0, defaultPreview.getWidth(), defaultPreview.getHeight());
+ dest.set(0, 0, finalPreviewWidth, finalPreviewHeight);
+
+ Paint p = sCachedAppWidgetPreviewPaint.get();
+ if (p == null) {
+ p = new Paint();
+ p.setFilterBitmap(true);
+ sCachedAppWidgetPreviewPaint.set(p);
+ }
+ c.drawBitmap(defaultPreview, src, dest, p);
+ c.setBitmap(null);
+ }
+ return preview;
+ }
+ public Drawable getFullResDefaultActivityIcon() {
+ return getFullResIcon(Resources.getSystem(),
+ android.R.mipmap.sym_def_app_icon);
+ }
+
+ public Drawable getFullResIcon(Resources resources, int iconId) {
+ Drawable d;
+ try {
+ d = resources.getDrawableForDensity(iconId, mIconDpi);
+ } catch (Resources.NotFoundException e) {
+ d = null;
+ }
+
+ return (d != null) ? d : getFullResDefaultActivityIcon();
+ }
+
+ public Drawable getFullResIcon(String packageName, int iconId) {
+ Resources resources;
+ try {
+ resources = mPackageManager.getResourcesForApplication(packageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ resources = null;
+ }
+ if (resources != null) {
+ if (iconId != 0) {
+ return getFullResIcon(resources, iconId);
+ }
+ }
+ return getFullResDefaultActivityIcon();
+ }
+
+ private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
+ renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f);
+ }
+
+ private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
+ float scale) {
+ if (bitmap != null) {
+ Canvas c = new Canvas(bitmap);
+ c.scale(scale, scale);
+ Rect oldBounds = d.copyBounds();
+ d.setBounds(x, y, x + w, y + h);
+ d.draw(c);
+ d.setBounds(oldBounds); // Restore the bounds
+ c.setBitmap(null);
+ }
+ }
+ }
}
@Override
public Item createItem(Context context, AppWidgetProviderInfo info, Bundle extras) {
CharSequence label = info.label;
- Drawable icon = null;
- if (info.icon != 0) {
- try {
- final Resources res = context.getResources();
- final int density = res.getDisplayMetrics().densityDpi;
- int iconDensity;
- switch (density) {
- case DisplayMetrics.DENSITY_MEDIUM:
- iconDensity = DisplayMetrics.DENSITY_LOW;
- case DisplayMetrics.DENSITY_TV:
- iconDensity = DisplayMetrics.DENSITY_MEDIUM;
- case DisplayMetrics.DENSITY_HIGH:
- iconDensity = DisplayMetrics.DENSITY_MEDIUM;
- case DisplayMetrics.DENSITY_XHIGH:
- iconDensity = DisplayMetrics.DENSITY_HIGH;
- case DisplayMetrics.DENSITY_XXHIGH:
- iconDensity = DisplayMetrics.DENSITY_XHIGH;
- default:
- // The density is some abnormal value. Return some other
- // abnormal value that is a reasonable scaling of it.
- iconDensity = (int)((density*0.75f)+.5f);
- }
- Resources packageResources = getPackageManager().
- getResourcesForApplication(info.provider.getPackageName());
- icon = packageResources.getDrawableForDensity(info.icon, iconDensity);
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon)
- + " for provider: " + info.provider);
- }
- if (icon == null) {
- Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon)
- + " for provider: " + info.provider);
- }
- }
-
- Item item = new Item(context, label, icon);
+ Item item = new Item(context, label);
+ item.appWidgetPreviewId = info.previewImage;
+ item.iconId = info.icon;
item.packageName = info.provider.getPackageName();
item.className = info.provider.getClassName();
item.extras = extras;
@@ -442,12 +496,19 @@
}
Item item = (Item) getItem(position);
- TextView textView = (TextView) convertView.findViewById(R.id.icon_and_label);
+ TextView textView = (TextView) convertView.findViewById(R.id.label);
textView.setText(item.label);
- textView.setCompoundDrawablesWithIntrinsicBounds(item.icon, null, null, null);
-
+ ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
+ iconView.setImageDrawable(null);
+ item.loadWidgetPreview(iconView);
return convertView;
}
+
+ public void cancelAllWidgetPreviewLoaders() {
+ for (int i = 0; i < mItems.size(); i++) {
+ mItems.get(i).cancelLoadingWidgetPreview();
+ }
+ }
}
/**
@@ -466,12 +527,13 @@
setResultData(result, intent);
} else {
try {
- Bundle options = null;
- if (intent.getExtras() != null) {
- options = intent.getExtras().getBundle(
- AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);
+ if (mAddingToKeyguard && mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
+ // Found in KeyguardHostView.java
+ final int KEYGUARD_HOST_ID = 0x4B455947;
+ mAppWidgetId = AppWidgetHost.allocateAppWidgetIdForSystem(KEYGUARD_HOST_ID);
}
- mAppWidgetManager.bindAppWidgetId(mAppWidgetId, intent.getComponent(), options);
+ mAppWidgetManager.bindAppWidgetId(
+ mAppWidgetId, intent.getComponent(), mExtraConfigureOptions);
result = RESULT_OK;
} catch (IllegalArgumentException e) {
// This is thrown if they're already bound, or otherwise somehow
@@ -491,9 +553,8 @@
}
protected void onDestroy() {
- if (!mSuccess && mAddingToKeyguard &&
- mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
- AppWidgetHost.deleteAppWidgetIdForSystem(mAppWidgetId);
+ if (mAppWidgetAdapter != null) {
+ mAppWidgetAdapter.cancelAllWidgetPreviewLoaders();
}
super.onDestroy();
}
@@ -502,20 +563,20 @@
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET) {
- int appWidgetId = (data == null) ? -1 : data.getIntExtra(
- AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
- if ((requestCode == REQUEST_PICK_APPWIDGET) &&
- resultCode == Activity.RESULT_OK) {
+ int appWidgetId;
+ if (data == null) {
+ appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID ;
+ } else {
+ appWidgetId = data.getIntExtra(
+ AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
+ }
+ if (requestCode == REQUEST_PICK_APPWIDGET && resultCode == Activity.RESULT_OK) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
- boolean defaultWidget =
- data.getBooleanExtra(LockPatternUtils.EXTRA_DEFAULT_WIDGET, false);
AppWidgetProviderInfo appWidget = null;
- if (!defaultWidget) {
- appWidget = appWidgetManager.getAppWidgetInfo(appWidgetId);
- }
+ appWidget = appWidgetManager.getAppWidgetInfo(appWidgetId);
- if (!defaultWidget && appWidget.configure != null) {
+ if (appWidget.configure != null) {
// Launch over to configure widget, if needed
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setComponent(appWidget.configure);
@@ -525,29 +586,31 @@
startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
} else {
// Otherwise just add it
- if (defaultWidget) {
- // If we selected "none", delete the allocated id
- AppWidgetHost.deleteAppWidgetIdForSystem(appWidgetId);
- data.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
- LockPatternUtils.ID_DEFAULT_STATUS_WIDGET);
- }
onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);
}
} else if (requestCode == REQUEST_CREATE_APPWIDGET && resultCode == Activity.RESULT_OK) {
- mSuccess = true;
mLockPatternUtils.addAppWidget(appWidgetId, 0);
- finishDelayedAndShowLockScreen();
+ finishDelayedAndShowLockScreen(appWidgetId);
} else {
- finishDelayedAndShowLockScreen();
+ if (mAddingToKeyguard &&
+ mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
+ AppWidgetHost.deleteAppWidgetIdForSystem(mAppWidgetId);
+ }
+ finishDelayedAndShowLockScreen(AppWidgetManager.INVALID_APPWIDGET_ID);
}
}
}
- private void finishDelayedAndShowLockScreen() {
+ private void finishDelayedAndShowLockScreen(int appWidgetId) {
IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
IWindowManager iWm = IWindowManager.Stub.asInterface(b);
+ Bundle opts = null;
+ if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
+ opts = new Bundle();
+ opts.putInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET, appWidgetId);
+ }
try {
- iWm.lockNow(null);
+ iWm.lockNow(opts);
} catch (RemoteException e) {
}