From 04d2d004a3eb74b9dd8e5e565c752c2497cd34a8 Mon Sep 17 00:00:00 2001 From: mvp76 Date: Tue, 28 Feb 2017 16:33:37 +0100 Subject: [PATCH] Add logic to show/hide notifications based on appdetails screen Also, add code to AppDetails2 to match AppDetails, keeping track of currently viewed app. Moved the nulling of this info to onStop instead of onPause, since alerts may be shown on top of the details page, while still visible. --- .../java/org/fdroid/fdroid/AppDetails.java | 39 +++++++++++---- .../java/org/fdroid/fdroid/AppDetails2.java | 47 ++++++++++++++++++- .../fdroid/fdroid/AppUpdateStatusManager.java | 10 ++++ .../org/fdroid/fdroid/NotificationHelper.java | 5 +- .../installer/InstallManagerService.java | 11 ++--- 5 files changed, 92 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/AppDetails.java b/app/src/main/java/org/fdroid/fdroid/AppDetails.java index dc8c00e9c..15e0539e4 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppDetails.java +++ b/app/src/main/java/org/fdroid/fdroid/AppDetails.java @@ -432,6 +432,12 @@ public class AppDetails extends AppCompatActivity { myAppObserver); } + @Override + protected void onResume() { + super.onResume(); + updateNotificationsForApp(); + } + @Override protected void onResumeFragments() { // Must be called before super.onResumeFragments(), as the fragments depend on the active @@ -462,13 +468,34 @@ public class AppDetails extends AppCompatActivity { protected void onStop() { super.onStop(); + visiblePackageName = null; getContentResolver().unregisterContentObserver(myAppObserver); + + // When leaving the app details, make sure to refresh app status for this app, since + // we might want to show notifications for it now. + updateNotificationsForApp(); + } + + /** + * Some notifications (like "downloading" and "installed") are not shown for this app if it is open in app details. + * When closing, we need to refresh the notifications, so they are displayed again. + */ + private void updateNotificationsForApp() { + if (app != null) { + AppUpdateStatusManager appUpdateStatusManager = AppUpdateStatusManager.getInstance(this); + for (AppUpdateStatusManager.AppUpdateStatus status : appUpdateStatusManager.getByPackageName(app.packageName)) { + if (status.status == AppUpdateStatusManager.Status.Installed) { + appUpdateStatusManager.removeApk(status.getUniqueKey()); + } else { + appUpdateStatusManager.refreshApk(status.getUniqueKey()); + } + } + } } @Override protected void onPause() { super.onPause(); - visiblePackageName = null; // save the active URL for this app in case we come back getPreferences(MODE_PRIVATE) .edit() @@ -554,7 +581,7 @@ public class AppDetails extends AppCompatActivity { String errorMessage = intent.getStringExtra(Installer.EXTRA_ERROR_MESSAGE); - if (!TextUtils.isEmpty(errorMessage)) { + if (!TextUtils.isEmpty(errorMessage) && !isFinishing()) { Log.e(TAG, "install aborted with errorMessage: " + errorMessage); String title = String.format( @@ -701,14 +728,6 @@ public class AppDetails extends AppCompatActivity { app = newApp; startingPrefs = app.getPrefs(this).createClone(); - - // Remove all "installed" statuses for this app, since we are now viewing it. - AppUpdateStatusManager appUpdateStatusManager = AppUpdateStatusManager.getInstance(this); - for (AppUpdateStatusManager.AppUpdateStatus status : appUpdateStatusManager.getByPackageName(app.packageName)) { - if (status.status == AppUpdateStatusManager.Status.Installed) { - appUpdateStatusManager.removeApk(status.getUniqueKey()); - } - } } private void refreshApkList() { diff --git a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java index 317f21084..d1c395d65 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java +++ b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java @@ -64,6 +64,16 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog private LocalBroadcastManager localBroadcastManager; private String activeDownloadUrlString; + /** + * Check if {@code packageName} is currently visible to the user. + */ + public static boolean isAppVisible(String packageName) { + return packageName != null && packageName.equals(visiblePackageName); + } + + private static String visiblePackageName; + + @Override protected void onCreate(Bundle savedInstanceState) { fdroidApp = (FDroidApp) getApplication(); @@ -131,6 +141,41 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog } } + /** + * Some notifications (like "downloading" and "installed") are not shown for this app if it is open in app details. + * When closing, we need to refresh the notifications, so they are displayed again. + */ + private void updateNotificationsForApp() { + if (app != null) { + AppUpdateStatusManager appUpdateStatusManager = AppUpdateStatusManager.getInstance(this); + for (AppUpdateStatusManager.AppUpdateStatus status : appUpdateStatusManager.getByPackageName(app.packageName)) { + if (status.status == AppUpdateStatusManager.Status.Installed) { + appUpdateStatusManager.removeApk(status.getUniqueKey()); + } else { + appUpdateStatusManager.refreshApk(status.getUniqueKey()); + } + } + } + } + + @Override + protected void onResume() { + super.onResume(); + if (app != null) { + visiblePackageName = app.packageName; + } + updateNotificationsForApp(); + } + + protected void onStop() { + super.onStop(); + visiblePackageName = null; + + // When leaving the app details, make sure to refresh app status for this app, since + // we might want to show notifications for it now. + updateNotificationsForApp(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { boolean ret = super.onCreateOptionsMenu(menu); @@ -372,7 +417,7 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog String errorMessage = intent.getStringExtra(Installer.EXTRA_ERROR_MESSAGE); - if (!TextUtils.isEmpty(errorMessage)) { + if (!TextUtils.isEmpty(errorMessage) && !isFinishing()) { Log.e(TAG, "install aborted with errorMessage: " + errorMessage); String title = String.format( diff --git a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java index 0ea683021..92ad49a82 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java +++ b/app/src/main/java/org/fdroid/fdroid/AppUpdateStatusManager.java @@ -237,6 +237,16 @@ public class AppUpdateStatusManager { } } + public void refreshApk(String key) { + synchronized (appMapping) { + AppUpdateStatus entry = appMapping.get(key); + if (entry != null) { + Utils.debugLog(LOGTAG, "Refresh APK " + entry.apk.apkName); + notifyChange(entry, true); + } + } + } + public void updateApkProgress(String key, int max, int current) { synchronized (appMapping) { AppUpdateStatus entry = appMapping.get(key); diff --git a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java index f1149601b..e06a27594 100644 --- a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java @@ -178,8 +178,9 @@ class NotificationHelper { // Ignore unknown status if (entry.status == AppUpdateStatusManager.Status.Unknown) return true; - // Ignore first time install downloads, assumed to be done from UI - else if (!entry.app.isInstalled() && (entry.status == AppUpdateStatusManager.Status.Downloading || entry.status == AppUpdateStatusManager.Status.ReadyToInstall)) + // Ignore downloading, readyToInstall and installError if we are showing the details screen for this app + else if ((entry.status == AppUpdateStatusManager.Status.Downloading || entry.status == AppUpdateStatusManager.Status.ReadyToInstall || entry.status == AppUpdateStatusManager.Status.InstallError) && + (AppDetails.isAppVisible(entry.app.packageName) || AppDetails2.isAppVisible(entry.app.packageName))) return true; return false; } 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 23fe520dd..ebd53031d 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -15,6 +15,7 @@ import android.text.TextUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.fdroid.fdroid.AppDetails; +import org.fdroid.fdroid.AppDetails2; import org.fdroid.fdroid.AppUpdateStatusManager; import org.fdroid.fdroid.Hasher; import org.fdroid.fdroid.Utils; @@ -313,17 +314,13 @@ public class InstallManagerService extends Service { localBroadcastManager.unregisterReceiver(this); break; case Installer.ACTION_INSTALL_INTERRUPTED: - AppUpdateStatusManager.AppUpdateStatus status = appUpdateStatusManager.get(downloadUrl); - appUpdateStatusManager.removeApk(downloadUrl); apk = intent.getParcelableExtra(Installer.EXTRA_APK); String errorMessage = intent.getStringExtra(Installer.EXTRA_ERROR_MESSAGE); - - // show notification if app details is not visible if (!TextUtils.isEmpty(errorMessage)) { - if (status == null || status.app == null || !AppDetails.isAppVisible(status.app.packageName)) { - appUpdateStatusManager.setApkError(apk, errorMessage); - } + appUpdateStatusManager.setApkError(apk, errorMessage); + } else { + appUpdateStatusManager.removeApk(downloadUrl); } localBroadcastManager.unregisterReceiver(this); break;