diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java index 73177384325..befc9e0b97a 100644 --- a/src/com/android/settings/CreateShortcut.java +++ b/src/com/android/settings/CreateShortcut.java @@ -59,14 +59,14 @@ public class CreateShortcut extends LauncherActivity { ResolveInfo resolveInfo = itemForPosition(position).resolveInfo; ActivityInfo activityInfo = resolveInfo.activityInfo; if (activityInfo.icon != 0) { - intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(activityInfo.icon)); + intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(this, activityInfo.icon)); } setResult(RESULT_OK, intent); finish(); } - private Bitmap createIcon(int resource) { - Context context = new ContextThemeWrapper(this, android.R.style.Theme_Material); + static Bitmap createIcon(Context ctx, int resource) { + Context context = new ContextThemeWrapper(ctx, android.R.style.Theme_Material); View view = LayoutInflater.from(context).inflate(R.layout.shortcut_badge, null); ((ImageView) view.findViewById(android.R.id.icon)).setImageResource(resource); diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 3209b51b1f4..b3df4a49430 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -43,6 +43,7 @@ import android.transition.TransitionManager; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; + import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; @@ -536,6 +537,8 @@ public class SettingsActivity extends SettingsDrawerActivity final ComponentName cn = intent.getComponent(); final String className = cn.getClassName(); + publishShortcuts(); + mIsShowingDashboard = className.equals(Settings.class.getName()) || className.equals(Settings.WirelessSettings.class.getName()) || className.equals(Settings.DeviceSettings.class.getName()) @@ -1016,6 +1019,18 @@ public class SettingsActivity extends SettingsDrawerActivity return f; } + private void publishShortcuts() { + AsyncTask.execute(new Runnable() { + @Override + public void run() { + if (!getSharedPreferences(ShortcutInfoPublisher.PREF_FILE, Context.MODE_PRIVATE) + .getBoolean(ShortcutInfoPublisher.PREF_KEY, false)) { + ShortcutInfoPublisher.setDynamicShortcuts(SettingsActivity.this, getTileCache()); + } + } + }); + } + private void updateTilesList() { // Generally the items that are will be changing from these updates will // not be in the top list of tiles, so run it in the background and the diff --git a/src/com/android/settings/ShortcutInfoPublisher.java b/src/com/android/settings/ShortcutInfoPublisher.java new file mode 100644 index 00000000000..893292ea881 --- /dev/null +++ b/src/com/android/settings/ShortcutInfoPublisher.java @@ -0,0 +1,134 @@ +package com.android.settings; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; +import android.graphics.drawable.Icon; +import android.util.Log; +import android.util.Pair; +import com.android.settingslib.drawer.Tile; +import com.android.settingslib.drawer.TileUtils; + +import java.util.*; + +/** + * Helper class that publish top 5 tiles to the {@link ShortcutManager}. + * + * Assumptions: + *
  • + * + * + *
  • + */ +public class ShortcutInfoPublisher { + private static boolean DBG = false; + private static String TAG = "ShortcutInfoPublisher"; + + public static String PREF_FILE = "shortcut_publisher"; + public static String PREF_KEY = "shortcut_published"; + + /** + * For any {@param dShortcutMap} if any of them requires updating because {@link Tile} is different, update. + * + * Note: Once ShortcutInfo.getTitle supports res id, this will NOT be required on Locale change. + * TODO: call on ACTION_LOCALE_CHANGED broadcast intent. + */ + public static void updateShortcuts(Context context, Collection tileList) { + ShortcutManager sm = context.getSystemService(ShortcutManager.class); + HashMap updateShortcutsMap = new HashMap<>(); + for (ShortcutInfo s: sm.getDynamicShortcuts()) { + updateShortcutsMap.put(s.getId(), s); + } + for (ShortcutInfo s: sm.getPinnedShortcuts()) { + updateShortcutsMap.put(s.getId(), s); + } + ArrayList updateShortcuts = new ArrayList<>(); + for(Tile t: tileList) { + if (publishedButChanged(updateShortcutsMap, t)){ + ShortcutInfo s = buildShortcutInfo(context, t); + updateShortcuts.add(s); + if (DBG) Log.d(TAG, "update: " + s.getId()); + } + } + // This check is not required if being called from foreground activity. + if (sm.getRemainingCallCount() > 0 && updateShortcuts.size() > 0) { + sm.updateShortcuts(updateShortcuts); + if (DBG) Log.d(TAG, "ShortcutManager.updateshortcuts: " + updateShortcuts.size()); + } + } + + /** + * Set the 5 top Tile as {@link ShortcutInfo}. + * + * Note: once one time loading of static list is supported, this will NOT be required. + */ + public static void setDynamicShortcuts(Context context, Map, Tile> tiles) { + ShortcutManager sm = context.getSystemService(ShortcutManager.class); + // Sort the tiles so that tiles with higher priority is at the beginning. + ArrayList tileList = new ArrayList<>(); + tileList.addAll(tiles.values()); + Collections.sort(tileList, TileUtils.TILE_COMPARATOR); + + int max = sm.getMaxDynamicShortcutCount(); + ArrayList dShortcutList = new ArrayList<>(); + for(Tile t: tileList) { + ShortcutInfo s = buildShortcutInfo(context, t); + dShortcutList.add(s); + if (DBG) Log.d(TAG, "add new shortcut: " + s.getId()); + if (dShortcutList.size() >= max) { + break; + } + } + // This check is not required if being called from foreground activity. + if (sm.getRemainingCallCount() > 0) { + sm.setDynamicShortcuts(dShortcutList); + if (DBG) Log.d(TAG, "ShortcutManager.setDynamicShortcuts"); + SharedPreferences sharedPref = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putBoolean(PREF_KEY, true); + editor.commit(); + } + } + + /** + * Extract string from {@link Tile} that should be used for shortcut id. + */ + private static String getShortcutInfoId(Tile t) { + return t.intent.getComponent().getShortClassName(); + } + + /** + * Build ShortcutInfo from given Tile. + */ + private static ShortcutInfo buildShortcutInfo(Context context, Tile t) { + return new ShortcutInfo.Builder(context) + .setId(getShortcutInfoId(t)) + .setTitle(t.title.toString()) + .setIntent(t.intent) + .setIcon(Icon.createWithBitmap(CreateShortcut.createIcon(context, t.icon.getResId()))) + .setWeight(t.priority) + .build(); + } + + private static boolean publishedButChanged(Map shortcutMap, Tile t) { + ShortcutInfo s = shortcutMap.get(getShortcutInfoId(t)); + if (s == null) { + return false; // never published. + } + if (t.priority != s.getWeight()) { + if (DBG) Log.d(TAG, s.getId() + " *weight* diff s:" + s.getWeight() + "t:" + t.priority); + return true; + } else if (!t.intent.equals(s.getIntent())) { + if (DBG) Log.d(TAG, s.getId() + " *intent* diff s:" + s.getIntent() + "t:" + t.intent); + return true; + } else if (!t.title.equals(s.getTitle())) { + if (DBG) Log.d(TAG, s.getId() + " *title* diff s:" + s.getTitle() + "t:" + t.title); + return true; + } else if (!t.icon.sameAs(s.getIcon())) { + if (DBG) Log.d(TAG, s.getId() + " *icon* diff s:" + s.getIcon() + "t:" + t.icon); + return true; + } + return false; + } +}