FAST icon indicating copy to clipboard operation
FAST copied to clipboard

Redesign the app (un)install receiver

Open SebiderSushi opened this issue 7 years ago • 11 comments

Currently the app install receiver causes some unecesary work:

  • It gets called multiple times for one single (un)installation: See here for more info about the Intent Actions necessary for the receiver - ADDED, CHANGED and FULLY_REMOVED should suffice.
  • It refreshes when an app gets uninstalled: Corresponding entries could simply be removed instead.
  • It always refreshes the whole list: The package name from the (un)installed app is included in the intent passed to onReceive() (but I couldn't yet find a way to query all the information that's needed by FAST for a single package).

Also I think the Receiver should delete corresponding icons from cache to either clean up when uninstalling or to cause an icon refresh for an updated application.

SebiderSushi avatar Sep 06 '17 19:09 SebiderSushi

I can implement this myself; the purpose of this issue is to get it acknowledged by @ligi (or someone else close to the project) and to find a way how to get a ResolveInfo object or something comparable for a specific package.

SebiderSushi avatar Sep 06 '17 19:09 SebiderSushi

Querying the full list from the Package Manager and then seeking the right one would be an option but that still seems a bit inefficient to me.

SebiderSushi avatar Sep 06 '17 19:09 SebiderSushi

Sounds great! I love efficiency - would be happy to merge a PR like this

ligi avatar Sep 06 '17 20:09 ligi

Okay I got it working. But the list gets refreshed in SearchActivity.onCreate() anyway and moving the refreshing part to onResume() would also remove the need of the receiver. However, if the target is efficiency, updating the list should only happen in the receiver. But then the list would depend on the reliability of the receiver being called. It should be pretty reliable though so a way to refresh manually should suffice for the exceptions, if there are any. A little testing could clear this up (See branch). So it's either refreshing everything and having a completely reliable list or using the receiver for efficiency.

SebiderSushi avatar Sep 07 '17 21:09 SebiderSushi

How far should efficiency go? Any arguments against directly modifying SearchActivity.appInfoList when refreshing?

SebiderSushi avatar Sep 09 '17 23:09 SebiderSushi

Okay I've been using this now for a couple of days (without direct modification of SearchActivity.appInfoList though) and it is very stable. I only had about one time when it did't get a newly installed app.

SebiderSushi avatar Sep 15 '17 18:09 SebiderSushi

I won't be able to clean up and polish it until the end of next week but I think it might still be neccesary to test this on some other devices anyway (maybe there could be some device dependent broadcast issues...don't know). (To test without direct modification of SearchActivity.appInfoList simply avoid that the reference to it gets publicly stored in App.appInfoList during SearchActivity.onCreate().)

Also I would measure the time it takes for the refreshing to complete and how to implement it at best since after reading about Broadcast Receivers I want to make sure that nothing gets killed before it's done.

SebiderSushi avatar Sep 15 '17 21:09 SebiderSushi

Concerning direct modification of SearchActivity.appInfoList: My basic thought was to save work by avoiding to merge two lists via DynamicAppInfoList.update() but my implementation feels kind of dirty and I think I've also been using a lot of bad practice there. I ultimately decided to drop the Idea after the implementation introduced some bugs like discarding information about hidden entries.

SebiderSushi avatar Sep 15 '17 21:09 SebiderSushi

The JobScheduler is not useful for subscribing to app list updates. What I figured out to be working instead might be updating the app list in SearchActivity.onCreate() and then registering for live app list updates. This could be implemented by using the currently used app list update mechanism and triggering a full refresh in onCreate() and registering for the affected Bradcasts at least at runtime, which is still permitted by Android.

Contemporary Alternative

Starting at API Level 21, there seems to be a new, better way for querying a list of installed apps & subscribing to changes in said list: LaucherApps This could replace the mechanisms in effect which are using Broadcasts and are always querying the full app list from the Package Manager when performing a complete refresh. Comparing the current activity list against the updated list returned by LauncherApps and then only querying necessary information from the Package Manager seems quicker and more efficient.

Currently, I'm about to implement this with full legacy support, i.e.: If running on Android Oreo or newer (Version Code 26+) FAST will use the LauncherApps class to keep its app list up to date. The existing methods using broadcasts will stay unchanged and take effect when broadcasts are received which will only happen if FAST is running on Nougat or earlier, since implicit broadcasts are still allowed there.

However, a cleaner way would be releasing 2 seperate versions of FAST, one for API levels up to 20 or 25, implementing the existing methods and one for API level 21 or higher, implementing the new method without registering the affected broadcasts in its receiver.

( This should be about the behaviour I've seen implemented in Trebuchet from Lineage 16.0, which is using LauncherApps to query information, does not register broadcasts related to package installs and specifies API level 23 as its minSdkVersion. )

SebiderSushi avatar May 04 '19 01:05 SebiderSushi

After some tests I've found out that it takes at least just as long to query a full activity list from LauncherApps service than to query from the Package Manager. Also I don't see anything in the LaucherApps Class that our logic could benefit from in terms of efficiency.

TL;DR: I'm just going to implement the update in onCreate if running on Oreo or newer and then register for the Broadcasts at run time.

SebiderSushi avatar May 11 '19 08:05 SebiderSushi

I have found a very interesting method in the Package Manager available on Android Oreo and Above.

I implemented this and now it allows FAST to use this to update it's app list when being launched on Android Oreo and above without having to refresh the whole list all the time.

The implementation should now be completely done and only needs to be tested and cleaned up now!

SebiderSushi avatar May 11 '19 13:05 SebiderSushi