From 89625ac355cb5bad8853a47bdd4fb049288e6956 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 13:12:51 +1000 Subject: [PATCH 01/10] Add selectable background to list items and cards. --- app/src/main/res/layout/app_card_featured.xml | 2 ++ app/src/main/res/layout/app_card_horizontal.xml | 4 +++- app/src/main/res/layout/app_card_large.xml | 4 +++- app/src/main/res/layout/app_card_list_item.xml | 4 +++- app/src/main/res/layout/app_list_item.xml | 4 +++- app/src/main/res/layout/installed_app_list_item.xml | 4 +++- 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/layout/app_card_featured.xml b/app/src/main/res/layout/app_card_featured.xml index a5d7b47e1..835b82f34 100644 --- a/app/src/main/res/layout/app_card_featured.xml +++ b/app/src/main/res/layout/app_card_featured.xml @@ -35,6 +35,8 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/header_height" + android:foreground="?attr/selectableItemBackground" + android:clickable="true" > + android:layout_height="wrap_content" + android:foreground="?attr/selectableItemBackground" + android:clickable="true"> + android:layout_height="220dp" + android:foreground="?attr/selectableItemBackground" + android:clickable="true"> + android:layout_height="wrap_content" + android:foreground="?attr/selectableItemBackground" + android:clickable="true"> + android:layout_height="wrap_content" + android:clickable="true" + android:background="?attr/selectableItemBackground"> diff --git a/app/src/main/res/layout/installed_app_list_item.xml b/app/src/main/res/layout/installed_app_list_item.xml index 764e202db..0ffc031ab 100644 --- a/app/src/main/res/layout/installed_app_list_item.xml +++ b/app/src/main/res/layout/installed_app_list_item.xml @@ -7,7 +7,9 @@ android:layout_height="wrap_content" android:padding="4dp" android:paddingTop="8dp" - android:paddingBottom="8dp"> + android:paddingBottom="8dp" + android:clickable="true" + android:background="?attr/selectableItemBackground"> From b5341efff9dbc13f7b37f8880d81e2358e2221eb Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 13:17:21 +1000 Subject: [PATCH 02/10] Don't padd the left/right of the category apps Doing so makes it appear like they scroll from somewhere which isn't quite the edge of the screen, which is weird. --- app/src/main/res/layout/category_item.xml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/res/layout/category_item.xml b/app/src/main/res/layout/category_item.xml index 4f6e717d8..3ad11f283 100644 --- a/app/src/main/res/layout/category_item.xml +++ b/app/src/main/res/layout/category_item.xml @@ -78,10 +78,6 @@ android:orientation="horizontal" android:paddingTop="@dimen/category_preview__app_list__padding__vertical" android:paddingBottom="@dimen/category_preview__app_list__padding__vertical" - android:clipToPadding="false" - android:layout_marginLeft="8dp" - android:layout_marginRight="8dp" - android:layout_marginStart="8dp" - android:layout_marginEnd="8dp" /> + android:clipToPadding="false" /> \ No newline at end of file From 0b7dc64fb67e4b14054e61d322fab827033e5dbe Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 13:26:56 +1000 Subject: [PATCH 03/10] Show apps in name order. Prior to this, they were in whatever order they came from the metadata. This resulted in weidrness because the repo which was updated last will have its apps shown last. We are trying to move away from the repo update order being important. In the future, this sort order should take into account better heuristics, but for now this is at least deterministic. --- .../main/java/org/fdroid/fdroid/views/apps/AppListActivity.java | 2 +- .../org/fdroid/fdroid/views/categories/CategoryController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListActivity.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListActivity.java index 2da8b69ce..991195d71 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListActivity.java @@ -121,7 +121,7 @@ public class AppListActivity extends AppCompatActivity implements LoaderManager. Schema.AppMetadataTable.Cols.ALL, null, null, - null + Schema.AppMetadataTable.Cols.NAME ); } diff --git a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java index aeb65eedd..10e99162a 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java @@ -153,7 +153,7 @@ public class CategoryController extends RecyclerView.ViewHolder implements Loade }, null, null, - null + Schema.AppMetadataTable.Cols.NAME ); } } From be11a785e5840d984f2245c95e72fb5f86060380 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 14:39:25 +1000 Subject: [PATCH 04/10] Make the "Updates" badge only show number of items needing action. Previously it showed the number of things which were eligible for update. This will become less and less important the more people we can switch over to automatic updates. However, given the privext vs unknown sources thing, we will always have a lot of users who need to be notified that they need to take further action to complete an install. --- .../fdroid/views/main/MainActivity.java | 72 ++++++++++--------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java index 759ac2358..571125aee 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java @@ -5,13 +5,9 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; -import android.support.v4.app.LoaderManager; -import android.support.v4.content.CursorLoader; -import android.support.v4.content.Loader; import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; @@ -32,9 +28,7 @@ import org.fdroid.fdroid.R; import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.compat.UriCompat; -import org.fdroid.fdroid.data.AppProvider; import org.fdroid.fdroid.data.NewRepoConfig; -import org.fdroid.fdroid.data.Schema; import org.fdroid.fdroid.views.ManageReposActivity; import org.fdroid.fdroid.views.apps.AppListActivity; import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; @@ -53,8 +47,7 @@ import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; * When switching from one screen to the next, we stay within this activity. The new screen will * get inflated (if required) */ -public class MainActivity extends AppCompatActivity implements BottomNavigationBar.OnTabSelectedListener, - LoaderManager.LoaderCallbacks { +public class MainActivity extends AppCompatActivity implements BottomNavigationBar.OnTabSelectedListener { private static final String TAG = "MainActivity"; @@ -66,8 +59,6 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB private static final String STATE_SELECTED_MENU_ID = "selectedMenuId"; - private static final int LOADER_NUM_UPDATES = 1; - private static final int REQUEST_SWAP = 3; private RecyclerView pager; @@ -89,7 +80,7 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB pager.setLayoutManager(new NonScrollingHorizontalLayoutManager(this)); pager.setAdapter(adapter); - updatesBadge = new BadgeItem(); + updatesBadge = new BadgeItem().hide(false); bottomNavigation = (BottomNavigationBar) findViewById(R.id.bottom_navigation); bottomNavigation.setTabSelectedListener(this) @@ -105,8 +96,8 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB .initialise(); IntentFilter updateableAppsFilter = new IntentFilter(AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED); + updateableAppsFilter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED); LocalBroadcastManager.getInstance(this).registerReceiver(onUpdateableAppsChanged, updateableAppsFilter); - getSupportLoaderManager().initLoader(LOADER_NUM_UPDATES, null, this); if (savedInstanceState != null) { selectedMenuId = savedInstanceState.getInt(STATE_SELECTED_MENU_ID, R.id.whats_new); @@ -319,22 +310,6 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB } } - @Override - public Loader onCreateLoader(int id, Bundle args) { - Uri uri = AppProvider.getCanUpdateUri(); - String[] projection = new String[]{Schema.AppMetadataTable.Cols._COUNT}; - - return new CursorLoader(this, uri, projection, null, null, null); - } - - @Override - public void onLoadFinished(Loader loader, Cursor cursor) { - cursor.moveToFirst(); - int canUpdateCount = cursor.getInt(cursor.getColumnIndex(Schema.AppMetadataTable.Cols._COUNT)); - cursor.close(); - refreshUpdatesBadge(canUpdateCount); - } - private void refreshUpdatesBadge(int canUpdateCount) { if (canUpdateCount == 0) { updatesBadge.hide(true); @@ -344,11 +319,6 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB } } - @Override - public void onLoaderReset(Loader loader) { - - } - private static class NonScrollingHorizontalLayoutManager extends LinearLayoutManager { NonScrollingHorizontalLayoutManager(Context context) { super(context, LinearLayoutManager.HORIZONTAL, false); @@ -365,11 +335,43 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB } } + /** + * There are a bunch of reasons why we would get notified about app statuses. + * The ones we are interested in are those which would result in the "items requiring user interaction" + * to increase or decrease: + * * Bulk updates of ready-to-install-apps (relating to {@link org.fdroid.fdroid.AppUpdateStatusService}. + * * Change in status to: + * * {@link AppUpdateStatusManager.Status#ReadyToInstall} (Causes the count to go UP by one) + * * {@link AppUpdateStatusManager.Status#Installed} (Causes the count to go DOWN by one) + */ private final BroadcastReceiver onUpdateableAppsChanged = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (AppUpdateStatusManager.REASON_UPDATES_AVAILABLE.equals(intent.getStringExtra(AppUpdateStatusManager.EXTRA_REASON_FOR_CHANGE))) { - getSupportLoaderManager().restartLoader(LOADER_NUM_UPDATES, null, MainActivity.this); + boolean updateBadge = false; + + AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context); + + if (AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED.equals(intent.getAction()) && + AppUpdateStatusManager.REASON_READY_TO_INSTALL.equals(intent.getStringExtra(AppUpdateStatusManager.EXTRA_REASON_FOR_CHANGE))) { + updateBadge = true; + } + + // Check if we have moved into the ReadyToInstall or Installed state. + AppUpdateStatusManager.AppUpdateStatus status = manager.get(intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL)); + boolean isStatusChange = intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false); + if (isStatusChange && status != null && (status.status == AppUpdateStatusManager.Status.ReadyToInstall || status.status == AppUpdateStatusManager.Status.Installed)) { + updateBadge = true; + } + + if (updateBadge) { + int count = 0; + for (AppUpdateStatusManager.AppUpdateStatus s : manager.getAll()) { + if (s.status == AppUpdateStatusManager.Status.ReadyToInstall) { + count++; + } + } + + refreshUpdatesBadge(count); } } }; From 8a69816648736328f90572254a964a6093e85db9 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 15:09:44 +1000 Subject: [PATCH 05/10] Only automatically redirect to package manager when viewing app. If you open AppDetails, initiate a download + install, and then navigate away, it still pops open the install dialog for you. This is because it never deregisters the broadcast receiver. This change maintains the behaviour of always having the broadcast receiver. This is because it is only added when the download completes, and would require further refactoring to change that. Instead, we listen for the receiver, but we ask if the AppDetails view for the apk in question is actually visible to the user. If not, we don't try to initiate the package manager. --- app/src/main/java/org/fdroid/fdroid/AppDetails2.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java index 55c2ac73f..f5122e0e5 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java +++ b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java @@ -457,8 +457,14 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog unregisterInstallReceiver(); break; case Installer.ACTION_INSTALL_USER_INTERACTION: - PendingIntent installPendingIntent = - intent.getParcelableExtra(Installer.EXTRA_USER_INTERACTION_PI); + Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK); + if (!isAppVisible(apk.packageName)) { + Utils.debugLog(TAG, "Ignore request for user interaction from installer, because " + apk.packageName + " is no longer showing."); + break; + } + + Utils.debugLog(TAG, "Automatically showing package manager for " + apk.packageName + " as it is being viewed by the user."); + PendingIntent installPendingIntent = intent.getParcelableExtra(Installer.EXTRA_USER_INTERACTION_PI); try { installPendingIntent.send(); From 2ab5c6a1c69b7421ad79a00c115b99439796a414 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 15:23:28 +1000 Subject: [PATCH 06/10] Correctly update the list item in updates view after install. Prior to this, it would still show the "Ready to update" list item. Now it updatpes the description to say "successfully installed" and removes the "Update" button. --- .../fdroid/fdroid/views/apps/AppListItemController.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java index d434582fa..08e349509 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java @@ -448,14 +448,15 @@ public class AppListItemController extends RecyclerView.ViewHolder { private final BroadcastReceiver onInstallAction = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (currentApp == null || installButton == null) { + Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK); + if (currentApp == null || !TextUtils.equals(apk.packageName, currentApp.packageName)) { return; } configureAppName(currentApp); + configureActionButton(currentApp); - Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK); - if (!TextUtils.equals(apk.packageName, currentApp.packageName)) { + if (installButton == null) { return; } From b0afa3e2fe931bd6afb996ecad961fb06ac7aa5e Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 15:41:57 +1000 Subject: [PATCH 07/10] Using custom icon for notification rather than the launcher icon. On newer devices, it takes the icon, removes colour, and uses that. This looks weird because: * The head and body look too close together once you remove the shading from the launcher icon. * The eyes dissapear because they are white (not transparent) in the launcher icon. --- .../main/java/org/fdroid/fdroid/NotificationHelper.java | 9 ++++----- app/src/main/res/drawable/ic_notification.xml | 7 +++++++ 2 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 app/src/main/res/drawable/ic_notification.xml diff --git a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java index 55e3625d4..298f2e65d 100644 --- a/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/NotificationHelper.java @@ -330,14 +330,13 @@ class NotificationHelper { App app = entry.app; AppUpdateStatusManager.Status status = entry.status; - int iconSmall = R.drawable.ic_launcher; Bitmap iconLarge = getLargeIconForEntry(entry); NotificationCompat.Builder builder = new NotificationCompat.Builder(context) .setAutoCancel(true) .setContentTitle(getSingleItemTitleString(app, status)) .setContentText(getSingleItemContentString(app, status)) - .setSmallIcon(iconSmall) + .setSmallIcon(R.drawable.ic_notification) .setColor(ContextCompat.getColor(context, R.color.fdroid_blue)) .setLargeIcon(iconLarge) .setLocalOnly(true) @@ -416,7 +415,7 @@ class NotificationHelper { NotificationCompat.Builder builder = new NotificationCompat.Builder(context) .setAutoCancel(!useStackedNotifications()) - .setSmallIcon(R.drawable.ic_launcher) + .setSmallIcon(R.drawable.ic_notification) .setColor(ContextCompat.getColor(context, R.color.fdroid_blue)) .setContentTitle(title) .setContentText(text) @@ -444,7 +443,7 @@ class NotificationHelper { new NotificationCompat.Builder(context) .setAutoCancel(true) .setLargeIcon(iconLarge) - .setSmallIcon(R.drawable.ic_launcher) + .setSmallIcon(R.drawable.ic_notification) .setColor(ContextCompat.getColor(context, R.color.fdroid_blue)) .setContentTitle(app.name) .setContentText(context.getString(R.string.notification_content_single_installed)) @@ -491,7 +490,7 @@ class NotificationHelper { NotificationCompat.Builder builder = new NotificationCompat.Builder(context) .setAutoCancel(!useStackedNotifications()) - .setSmallIcon(R.drawable.ic_launcher) + .setSmallIcon(R.drawable.ic_notification) .setColor(ContextCompat.getColor(context, R.color.fdroid_blue)) .setContentTitle(title) .setContentText(text) diff --git a/app/src/main/res/drawable/ic_notification.xml b/app/src/main/res/drawable/ic_notification.xml new file mode 100644 index 000000000..b34e2a5ff --- /dev/null +++ b/app/src/main/res/drawable/ic_notification.xml @@ -0,0 +1,7 @@ + + + From 50044629ab38ec73c9bf0d7b99d4f3017dc216ee Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 15:50:17 +1000 Subject: [PATCH 08/10] Remove placeholder whatsNew text completely. Now that we are releasing this, we need to remove the "Whats New" placeholder text. --- .../views/AppDetailsRecyclerViewAdapter.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java index a85b05672..94de54327 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java @@ -35,7 +35,6 @@ import android.widget.Toast; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.ImageScaleType; -import org.fdroid.fdroid.BuildConfig; import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.R; import org.fdroid.fdroid.Utils; @@ -413,15 +412,12 @@ public class AppDetailsRecyclerViewAdapter } else { lastUpdateView.setVisibility(View.GONE); } + Apk suggestedApk = getSuggestedApk(); - // TODO replace this whatsNew test code with what comes from suggestedApk once that exists - //if (suggestedApk == null || TextUtils.isEmpty(suggestedApk.whatsNew)) { + + // TODO populate whatsNew with suggestedApk.whatsNew once that exists String whatsNew = null; - if (BuildConfig.DEBUG) { - if (Math.random() > 0.5) { - whatsNew = "This section will contain the 'what's new' information for the apk.\n\n\t• Bug fixes."; - } - } + //noinspection ConstantConditions if (suggestedApk == null || TextUtils.isEmpty(whatsNew)) { whatsNewView.setVisibility(View.GONE); } else { @@ -431,7 +427,7 @@ public class AppDetailsRecyclerViewAdapter StringBuilder sbWhatsNew = new StringBuilder(); sbWhatsNew.append(whatsNewView.getContext().getString(R.string.details_new_in_version, suggestedApk.versionName).toUpperCase(locale)); sbWhatsNew.append("\n\n"); - sbWhatsNew.append("This section will contain the 'what's new' information for the apk.\n\n\t• Bug fixes."); + sbWhatsNew.append(whatsNew); whatsNewView.setText(sbWhatsNew); whatsNewView.setVisibility(View.VISIBLE); } From 24a6e9590ddadb6ff1724e5c01a28fcc8147696a Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 16:27:37 +1000 Subject: [PATCH 09/10] Wait until installed app service is ready before updating app details. We were jumping the gun before, and asking to refresh the app details adapter before the installed app service was able to notify us of a change to the apps installed version. This should be refactored to use broadcast receivers instead of content observers (which are tied to the implementation of a content provider). However this is currently a straight port from app details 1 to app details 2. --- .../java/org/fdroid/fdroid/AppDetails2.java | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java index f5122e0e5..4917be1c1 100644 --- a/app/src/main/java/org/fdroid/fdroid/AppDetails2.java +++ b/app/src/main/java/org/fdroid/fdroid/AppDetails2.java @@ -9,8 +9,10 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CoordinatorLayout; import android.support.v4.content.LocalBroadcastManager; @@ -188,6 +190,13 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog if (app != null) { visiblePackageName = app.packageName; } + + appObserver = new AppObserver(new Handler()); + getContentResolver().registerContentObserver( + AppProvider.getHighestPriorityMetadataUri(app.packageName), + true, + appObserver); + updateNotificationsForApp(); } @@ -195,6 +204,8 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog super.onStop(); visiblePackageName = null; + getContentResolver().unregisterContentObserver(appObserver); + // 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(); @@ -432,7 +443,9 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog case Installer.ACTION_INSTALL_COMPLETE: adapter.clearProgress(); unregisterInstallReceiver(); - onAppChanged(); + // Don't try and update the view here, because the InstalledAppProviderService + // hasn't had time to do its thing and mark the app as installed. Instead, we + // wait for that service to notify us, and then we will respond in appObserver. break; case Installer.ACTION_INSTALL_INTERRUPTED: adapter.clearProgress(); @@ -655,4 +668,26 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog } startUninstall(); } + + // observer to update view when package has been installed/deleted + private AppObserver appObserver; + + class AppObserver extends ContentObserver { + + AppObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + onChange(selfChange, null); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + onAppChanged(); + } + + } + } From 8faf151c9038a3f9c8d7749ba9eced7c8ef2d1f0 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 5 Apr 2017 16:42:58 +1000 Subject: [PATCH 10/10] Remove 1 second pause between installing and updating UI. This was implemented before because the main screen of the three tab layout needed to update in response to the list of installed apps being installed. When we scan the list of installed apps upon starting F-Droid, we didn't want to have to requery for the list of installed apps every time we found a new installed app. For this reason, we "debounced" these requests (accumulated them for 1 second, and then let go of a notification only after 1 second of inactivity). This is no longer a feature, and so we can afford to fire the notification instantly. --- .../org/fdroid/fdroid/data/InstalledAppProviderService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java index 6f0dee7fb..67c92743b 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java @@ -21,7 +21,6 @@ import java.io.FilenameFilter; import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import rx.functions.Action1; import rx.schedulers.Schedulers; @@ -64,7 +63,7 @@ public class InstalledAppProviderService extends IntentService { public void onCreate() { super.onCreate(); notifyEvents = PublishSubject.create(); - notifyEvents.debounce(1, TimeUnit.SECONDS) + notifyEvents .subscribeOn(Schedulers.newThread()) .subscribe(new Action1() { @Override