From 08ffaae3b627a124eaaf8610f5ea8f1898700d45 Mon Sep 17 00:00:00 2001 From: Mario Bertschler Date: Mon, 20 Mar 2017 11:30:27 -0700 Subject: [PATCH] Show promise app icon progress in All Apps and setup market intent on clicking promise app icon in All Apps. Only the progress will be changed with animation on progress update, no relayout is performed. If the icon is newly bound, the progress will not be animated. Bug: 23952570 Change-Id: I98d3f945f08a2abadf53f20e6007c15e56d5d410 --- src/com/android/launcher3/BubbleTextView.java | 32 +++++++++++++------ src/com/android/launcher3/InfoDropTarget.java | 6 ++++ src/com/android/launcher3/Launcher.java | 24 +++++++++++++- src/com/android/launcher3/LauncherModel.java | 1 + src/com/android/launcher3/PromiseAppInfo.java | 5 +++ .../allapps/AllAppsContainerView.java | 13 ++++++++ .../model/PackageInstallStateChangedTask.java | 11 +++---- 7 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index f9a6742d8f..add0185ba5 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -39,7 +39,6 @@ import com.android.launcher3.IconCache.IconLoadRequest; import com.android.launcher3.IconCache.ItemInfoUpdateReceiver; import com.android.launcher3.badge.BadgeInfo; import com.android.launcher3.badge.BadgeRenderer; -import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.FolderIconPreviewVerifier; import com.android.launcher3.graphics.DrawableFactory; import com.android.launcher3.graphics.HolographicOutlineHelper; @@ -181,6 +180,10 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver { // Verify high res immediately verifyHighRes(); + if (info instanceof PromiseAppInfo) { + PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info; + applyProgressLevel(promiseAppInfo.level); + } applyBadgeState(info, false /* animate */); } @@ -476,27 +479,36 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver { ((info.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE) ? info.getInstallProgress() : 0)) : 100; - setContentDescription(progressLevel > 0 ? - getContext().getString(R.string.app_downloading_title, info.title, - NumberFormat.getPercentInstance().format(progressLevel * 0.01)) : - getContext().getString(R.string.app_waiting_download_title, info.title)); + PreloadIconDrawable preloadDrawable = applyProgressLevel(progressLevel); + if (preloadDrawable != null && promiseStateChanged) { + preloadDrawable.maybePerformFinishedAnimation(); + } + } + } + + public PreloadIconDrawable applyProgressLevel(int progressLevel) { + if (getTag() instanceof ItemInfoWithIcon) { + ItemInfoWithIcon info = (ItemInfoWithIcon) getTag(); + setContentDescription(progressLevel > 0 + ? getContext().getString(R.string.app_downloading_title, info.title, + NumberFormat.getPercentInstance().format(progressLevel * 0.01)) + : getContext().getString(R.string.app_waiting_download_title, info.title)); if (mIcon != null) { final PreloadIconDrawable preloadDrawable; if (mIcon instanceof PreloadIconDrawable) { preloadDrawable = (PreloadIconDrawable) mIcon; + preloadDrawable.setLevel(progressLevel); } else { preloadDrawable = DrawableFactory.get(getContext()) .newPendingIcon(info.iconBitmap, getContext()); + preloadDrawable.setLevel(progressLevel); setIcon(preloadDrawable); } - - preloadDrawable.setLevel(progressLevel); - if (promiseStateChanged) { - preloadDrawable.maybePerformFinishedAnimation(); - } + return preloadDrawable; } } + return null; } public void applyBadgeState(ItemInfo itemInfo, boolean animate) { diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java index 34adf47a18..2f61a01ed7 100644 --- a/src/com/android/launcher3/InfoDropTarget.java +++ b/src/com/android/launcher3/InfoDropTarget.java @@ -60,6 +60,12 @@ public class InfoDropTarget extends UninstallDropTarget { */ public static boolean startDetailsActivityForInfo( ItemInfo info, Launcher launcher, DropTargetResultCallback callback) { + if (info instanceof PromiseAppInfo) { + PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info; + launcher.startActivity(promiseAppInfo.getMarketIntent()); + return true; + } + boolean result = false; ComponentName componentName = null; if (info instanceof AppInfo) { diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index d5baabfc00..c7f0b4748a 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -2454,7 +2454,13 @@ public class Launcher extends BaseActivity private void startAppShortcutOrInfoActivity(View v) { ItemInfo item = (ItemInfo) v.getTag(); - Intent intent = item.getIntent(); + Intent intent; + if (item instanceof PromiseAppInfo) { + PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item; + intent = promiseAppInfo.getMarketIntent(); + } else { + intent = item.getIntent(); + } if (intent == null) { throw new IllegalArgumentException("Input must have a valid intent"); } @@ -3762,6 +3768,22 @@ public class Launcher extends BaseActivity } } + @Override + public void bindPromiseAppProgressUpdated(final PromiseAppInfo app) { + Runnable r = new Runnable() { + public void run() { + bindPromiseAppProgressUpdated(app); + } + }; + if (waitUntilResume(r)) { + return; + } + + if (mAppsView != null) { + mAppsView.updatePromiseAppProgress(app); + } + } + @Override public void bindWidgetsRestored(final ArrayList widgets) { Runnable r = new Runnable() { diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 707ec8642d..39b9dd3d2c 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -195,6 +195,7 @@ public class LauncherModel extends BroadcastReceiver ArrayList addAnimated, ArrayList addedApps); public void bindAppsUpdated(ArrayList apps); + public void bindPromiseAppProgressUpdated(PromiseAppInfo app); public void bindShortcutsChanged(ArrayList updated, ArrayList removed, UserHandle user); public void bindWidgetsRestored(ArrayList widgets); diff --git a/src/com/android/launcher3/PromiseAppInfo.java b/src/com/android/launcher3/PromiseAppInfo.java index 04ba1d366f..1749dde088 100644 --- a/src/com/android/launcher3/PromiseAppInfo.java +++ b/src/com/android/launcher3/PromiseAppInfo.java @@ -20,6 +20,7 @@ import android.content.Intent; import android.support.annotation.NonNull; import com.android.launcher3.compat.PackageInstallerCompat; +import com.android.launcher3.util.PackageManagerHelper; public class PromiseAppInfo extends AppInfo { @@ -44,4 +45,8 @@ public class PromiseAppInfo extends AppInfo { shortcut.status |= ShortcutInfo.FLAG_RESTORE_STARTED; return shortcut; } + + public Intent getMarketIntent() { + return PackageManagerHelper.getMarketIntent(componentName.getPackageName()); + } } diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index cc5fa8ce15..7219141cd3 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -37,6 +37,7 @@ import android.view.ViewGroup; import com.android.launcher3.AppInfo; import com.android.launcher3.BaseContainerView; +import com.android.launcher3.BubbleTextView; import com.android.launcher3.DeleteDropTarget; import com.android.launcher3.DeviceProfile; import com.android.launcher3.DragSource; @@ -45,6 +46,7 @@ import com.android.launcher3.ExtendedEditText; import com.android.launcher3.Insettable; import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; +import com.android.launcher3.PromiseAppInfo; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; @@ -158,6 +160,17 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc mSearchBarController.refreshSearchResult(); } + public void updatePromiseAppProgress(PromiseAppInfo app) { + int childCount = mAppsRecyclerView.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = mAppsRecyclerView.getChildAt(i); + if (child instanceof BubbleTextView && child.getTag() == app) { + BubbleTextView bubbleTextView = (BubbleTextView) child; + bubbleTextView.applyProgressLevel(app.level); + } + } + } + /** * Removes some apps from the list. */ diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java index 9c5f18917e..f8793e0788 100644 --- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java +++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java @@ -51,7 +51,7 @@ public class PackageInstallStateChangedTask extends ExtendedModelTask { } synchronized (apps) { - final ArrayList updated = new ArrayList<>(); + PromiseAppInfo updated = null; final ArrayList removed = new ArrayList<>(); for (int i=0; i < apps.size(); i++) { final AppInfo appInfo = apps.get(i); @@ -61,7 +61,7 @@ public class PackageInstallStateChangedTask extends ExtendedModelTask { final PromiseAppInfo promiseAppInfo = (PromiseAppInfo) appInfo; if (mInstallInfo.state == PackageInstallerCompat.STATUS_INSTALLING) { promiseAppInfo.level = mInstallInfo.progress; - updated.add(appInfo); + updated = promiseAppInfo; } else if (mInstallInfo.state == PackageInstallerCompat.STATUS_FAILED || mInstallInfo.state == PackageInstallerCompat.STATUS_INSTALLED) { apps.removePromiseApp(appInfo); @@ -70,13 +70,12 @@ public class PackageInstallStateChangedTask extends ExtendedModelTask { } } } - if (!updated.isEmpty()) { + if (updated != null) { + final PromiseAppInfo updatedPromiseApp = updated; scheduleCallbackTask(new CallbackTask() { @Override public void execute(Callbacks callbacks) { - // TODO: this currently causes unnecessary relayouts - // we need to introduce a new bindPromiseAppsChanged - callbacks.bindAppsUpdated(updated); + callbacks.bindPromiseAppProgressUpdated(updatedPromiseApp); } }); }