From 48c7a93eb7ef15ef551aee80c179b8e7e0d2399a Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Tue, 14 May 2013 20:17:58 +0200 Subject: Persist list of shortcuts to install on home workspace Bug: 8707110 Change-Id: I6740350040dceb0edaf4295d6a5af62a088a3055 --- .../android/launcher2/InstallShortcutReceiver.java | 113 +++++++++++++++++++-- 1 file changed, 106 insertions(+), 7 deletions(-) diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java index 337097e4b..2e86a7f05 100644 --- a/src/com/android/launcher2/InstallShortcutReceiver.java +++ b/src/com/android/launcher2/InstallShortcutReceiver.java @@ -22,6 +22,10 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.util.Base64; +import android.util.Log; import android.widget.Toast; import com.android.launcher.R; @@ -31,12 +35,23 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import org.json.*; + public class InstallShortcutReceiver extends BroadcastReceiver { public static final String ACTION_INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT"; public static final String NEW_APPS_PAGE_KEY = "apps.new.page"; public static final String NEW_APPS_LIST_KEY = "apps.new.list"; + public static final String DATA_INTENT_KEY = "intent.data"; + public static final String LAUNCH_INTENT_KEY = "intent.launch"; + public static final String NAME_KEY = "name"; + public static final String ICON_KEY = "icon"; + public static final String ICON_RESOURCE_NAME_KEY = "iconResource"; + public static final String ICON_RESOURCE_PACKAGE_NAME_KEY = "iconResourcePackage"; + // The set of shortcuts that are pending install + public static final String APPS_PENDING_INSTALL = "apps_to_install"; + public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450; public static final int NEW_SHORTCUT_STAGGER_DELAY = 75; @@ -50,10 +65,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver { private static Object sLock = new Object(); - // The set of shortcuts that are pending install - private static ArrayList mInstallQueue = - new ArrayList(); - private static void addToStringSet(SharedPreferences sharedPrefs, SharedPreferences.Editor editor, String key, String value) { Set strings = sharedPrefs.getStringSet(key, null); @@ -65,6 +76,82 @@ public class InstallShortcutReceiver extends BroadcastReceiver { strings.add(value); editor.putStringSet(key, strings); } + + private static void addToInstallQueue( + SharedPreferences sharedPrefs, PendingInstallShortcutInfo info) { + synchronized(sLock) { + try { + JSONStringer json = new JSONStringer() + .object() + .key(DATA_INTENT_KEY).value(info.data.toUri(0)) + .key(LAUNCH_INTENT_KEY).value(info.launchIntent.toUri(0)) + .key(NAME_KEY).value(info.name); + if (info.icon != null) { + byte[] iconByteArray = ItemInfo.flattenBitmap(info.icon); + json = json.key(ICON_KEY).value( + Base64.encodeToString( + iconByteArray, 0, iconByteArray.length, Base64.DEFAULT)); + } + if (info.iconResource != null) { + json = json.key(ICON_RESOURCE_NAME_KEY).value(info.iconResource.resourceName); + json = json.key(ICON_RESOURCE_PACKAGE_NAME_KEY) + .value(info.iconResource.packageName); + } + json = json.endObject(); + SharedPreferences.Editor editor = sharedPrefs.edit(); + addToStringSet(sharedPrefs, editor, APPS_PENDING_INSTALL, json.toString()); + editor.commit(); + } catch (org.json.JSONException e) { + Log.d("InstallShortcutReceiver", "Exception when adding shortcut: " + e); + } + } + } + + private static ArrayList getAndClearInstallQueue( + SharedPreferences sharedPrefs) { + synchronized(sLock) { + Set strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null); + if (strings == null) { + return new ArrayList(); + } + ArrayList infos = + new ArrayList(); + for (String json : strings) { + try { + JSONObject object = (JSONObject) new JSONTokener(json).nextValue(); + Intent data = Intent.parseUri(object.getString(DATA_INTENT_KEY), 0); + Intent launchIntent = Intent.parseUri(object.getString(LAUNCH_INTENT_KEY), 0); + String name = object.getString(NAME_KEY); + String iconBase64 = object.optString(ICON_KEY); + String iconResourceName = object.optString(ICON_RESOURCE_NAME_KEY); + String iconResourcePackageName = + object.optString(ICON_RESOURCE_PACKAGE_NAME_KEY); + if (iconBase64 != null && !iconBase64.isEmpty()) { + byte[] iconArray = Base64.decode(iconBase64, Base64.DEFAULT); + Bitmap b = BitmapFactory.decodeByteArray(iconArray, 0, iconArray.length); + data.putExtra(Intent.EXTRA_SHORTCUT_ICON, b); + } else if (iconResourceName != null && !iconResourceName.isEmpty()) { + Intent.ShortcutIconResource iconResource = + new Intent.ShortcutIconResource(); + iconResource.resourceName = iconResourceName; + iconResource.packageName = iconResourcePackageName; + data.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource); + } + data.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launchIntent); + PendingInstallShortcutInfo info = + new PendingInstallShortcutInfo(data, name, launchIntent); + infos.add(info); + } catch (org.json.JSONException e) { + Log.d("InstallShortcutReceiver", "Exception reading shortcut to add: " + e); + } catch (java.net.URISyntaxException e) { + Log.d("InstallShortcutReceiver", "Exception reading shortcut to add: " + e); + } + } + sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, new HashSet()).commit(); + return infos; + } + } + // Determines whether to defer installing shortcuts immediately until // processAllPendingInstalls() is called. private static boolean mUseInstallQueue = false; @@ -73,6 +160,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver { Intent data; Intent launchIntent; String name; + Bitmap icon; + Intent.ShortcutIconResource iconResource; public PendingInstallShortcutInfo(Intent rawData, String shortcutName, Intent shortcutIntent) { @@ -103,13 +192,21 @@ public class InstallShortcutReceiver extends BroadcastReceiver { return; } } + Bitmap icon = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON); + Intent.ShortcutIconResource iconResource = + data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE); + // Queue the item up for adding if launcher has not loaded properly yet boolean launcherNotLoaded = LauncherModel.getCellCountX() <= 0 || LauncherModel.getCellCountY() <= 0; PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, name, intent); + info.icon = icon; + info.iconResource = iconResource; if (mUseInstallQueue || launcherNotLoaded) { - mInstallQueue.add(info); + String spKey = LauncherApplication.getSharedPreferencesKey(); + SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE); + addToInstallQueue(sp, info); } else { processInstallShortcut(context, info); } @@ -123,10 +220,12 @@ public class InstallShortcutReceiver extends BroadcastReceiver { flushInstallQueue(context); } static void flushInstallQueue(Context context) { - Iterator iter = mInstallQueue.iterator(); + String spKey = LauncherApplication.getSharedPreferencesKey(); + SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE); + ArrayList installQueue = getAndClearInstallQueue(sp); + Iterator iter = installQueue.iterator(); while (iter.hasNext()) { processInstallShortcut(context, iter.next()); - iter.remove(); } } -- cgit v1.2.3