From 8ed62d22e14a43072fcf5d5f790f3876f73e08d4 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Thu, 23 Mar 2017 22:15:13 +1100 Subject: [PATCH] Correctly listen for "Install complete" for previously downloaded apks. This ensures that if the user has downloaded an update (manually or via auto updates), then the UI will respond correctly once it is installed. --- .../fdroid/fdroid/AppUpdateStatusService.java | 2 + .../installer/InstallManagerService.java | 38 ++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusService.java b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusService.java index f9b0e370c..b3b43b54a 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusService.java +++ b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusService.java @@ -12,6 +12,7 @@ import org.fdroid.fdroid.data.App; import org.fdroid.fdroid.data.AppProvider; import org.fdroid.fdroid.data.Schema; import org.fdroid.fdroid.installer.ApkCache; +import org.fdroid.fdroid.installer.InstallManagerService; import java.util.ArrayList; import java.util.List; @@ -53,5 +54,6 @@ public class AppUpdateStatusService extends IntentService { } AppUpdateStatusManager.getInstance(this).addApks(apksReadyToInstall, AppUpdateStatusManager.Status.ReadyToInstall); + InstallManagerService.managePreviouslyDownloadedApks(this); } } \ No newline at end of file diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java index 51cc09f3d..7a80f3fc5 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -68,6 +68,16 @@ public class InstallManagerService extends Service { private static final String ACTION_INSTALL = "org.fdroid.fdroid.installer.action.INSTALL"; private static final String ACTION_CANCEL = "org.fdroid.fdroid.installer.action.CANCEL"; + /** + * The install manager service needs to monitor downloaded apks so that it can wait for a user to + * install them and respond accordingly. Usually the thing which starts listening for such events + * does so directly after a download is complete. This works great, except when the user then + * subsequently closes F-Droid and opens it at a later date. Under these circumstances, a background + * service will scan all downloaded apks and notify the user about them. When it does so, the + * install manager service needs to add listeners for if the apks get installed. + */ + private static final String ACTION_MANAGE_DOWNLOADED_APKS = "org.fdroid.fdroid.installer.action.ACTION_MANAGE_DOWNLOADED_APKS"; + private static final String EXTRA_APP = "org.fdroid.fdroid.installer.extra.APP"; private static final String EXTRA_APK = "org.fdroid.fdroid.installer.extra.APK"; @@ -108,13 +118,19 @@ public class InstallManagerService extends Service { public int onStartCommand(Intent intent, int flags, int startId) { Utils.debugLog(TAG, "onStartCommand " + intent); + String action = intent.getAction(); + + if (ACTION_MANAGE_DOWNLOADED_APKS.equals(action)) { + registerInstallerReceiversForDownlaodedApks(); + return START_NOT_STICKY; + } + String urlString = intent.getDataString(); if (TextUtils.isEmpty(urlString)) { Utils.debugLog(TAG, "empty urlString, nothing to do"); return START_NOT_STICKY; } - String action = intent.getAction(); if (ACTION_CANCEL.equals(action)) { DownloaderService.cancel(this, urlString); Apk apk = appUpdateStatusManager.getApk(urlString); @@ -292,6 +308,20 @@ public class InstallManagerService extends Service { DownloaderService.getIntentFilter(urlString)); } + /** + * For each app in the {@link AppUpdateStatusManager.Status#ReadyToInstall} state, setup listeners + * so that if the user installs it then we can respond accordingly. This makes sure that whether + * the user just finished downloading it, or whether they downloaded it a day ago but have not yet + * installed it, we get the same experience upon completing an install. + */ + private void registerInstallerReceiversForDownlaodedApks() { + for (AppUpdateStatusManager.AppUpdateStatus appStatus : AppUpdateStatusManager.getInstance(this).getAll()) { + if (appStatus.status == AppUpdateStatusManager.Status.ReadyToInstall) { + registerInstallerReceivers(Uri.parse(appStatus.getUniqueKey())); + } + } + } + private void registerInstallerReceivers(Uri downloadUri) { BroadcastReceiver installReceiver = new BroadcastReceiver() { @@ -363,4 +393,10 @@ public class InstallManagerService extends Service { intent.setData(Uri.parse(urlString)); context.startService(intent); } + + public static void managePreviouslyDownloadedApks(Context context) { + Intent intent = new Intent(context, InstallManagerService.class); + intent.setAction(ACTION_MANAGE_DOWNLOADED_APKS); + context.startService(intent); + } }