3
3
import android .content .BroadcastReceiver ;
4
4
import android .content .Context ;
5
5
import android .content .Intent ;
6
+ import android .content .pm .ResolveInfo ;
7
+ import android .net .Uri ;
8
+
6
9
import org .ligi .fast .App ;
10
+ import org .ligi .fast .model .AppInfo ;
7
11
import org .ligi .fast .model .AppInfoList ;
8
12
import org .ligi .fast .util .AppInfoListStore ;
9
13
14
+ import java .io .File ;
15
+ import java .util .Iterator ;
16
+ import java .util .List ;
17
+
18
+ /**
19
+ * Whenever an app is installed, uninstalled or components change
20
+ * (e.g. the app disabled one of it's activities to hide it from the launcher)
21
+ * this receiver takes care of removing or updating corresponding entries
22
+ * (namely all activities and aliases) from AppInfoList and deletes their icons
23
+ * from cache to clean up when uninstalling or to cause a refresh when updating.
24
+ */
10
25
public class AppInstallOrRemoveReceiver extends BroadcastReceiver {
26
+ //public final static String LOG_TAG = "FAST.AppInstallOrRemoveReceiver";
27
+
11
28
@ Override
12
29
public void onReceive (Context context , Intent intent ) {
13
- final AppInfoListStore appInfoListStore = new AppInfoListStore (context );
30
+ Uri data = intent .getData ();
31
+ if (data == null ) return ; // This should never be the case but...just to be sure...
32
+ String packageName = data .getSchemeSpecificPart ();
33
+ String action = intent .getAction ();
34
+ AppInfoListStore appInfoListStore = new AppInfoListStore (context );
35
+ AppInfoList appInfoList = null ;
36
+ if (App .backingAppInfoList != null ) {
37
+ appInfoList = App .backingAppInfoList .get ();
38
+ }
39
+ if (appInfoList == null ) {
40
+ appInfoList = appInfoListStore .load ();
41
+ }
42
+ // Check the package is newly installed or not
43
+ // getBooleanExtra defaultValue is true so that in case of doubt the
44
+ // presence of old information is checked anyway
45
+ boolean newInstall = Intent .ACTION_PACKAGE_ADDED .equals (action ) && !intent .getBooleanExtra (Intent .EXTRA_REPLACING , true );
46
+ AppInfoList matchedAppInfoList = new AppInfoList ();
47
+ if (!newInstall ) {
48
+ // Collect all information concerning the changed package
49
+ Iterator <AppInfo > appInfoIterator = appInfoList .iterator ();
50
+ while (appInfoIterator .hasNext ()) {
51
+ AppInfo appInfo = appInfoIterator .next ();
52
+ if (appInfo .getPackageName ().equals (packageName )) {
53
+ matchedAppInfoList .add (appInfo );
54
+ appInfoIterator .remove ();
55
+ File icon = appInfo .getIconCacheFile ();
56
+ icon .delete ();
57
+ /*
58
+ if (!icon.delete()) {
59
+ Log.d(App.LOG_TAG, "AppInstallOrRemoveReceiver: Icon deletion failed for hash: " + appInfo.getHash());
60
+ Log.d(AppInstallOrRemoveReceiver.LOG_TAG, "Icon deletion failed for hash: " + appInfo.getHash());
61
+ }
62
+ */
63
+ }
64
+ }
65
+ // Just to be sure; If this is the case there is no old information
66
+ // to update and we can continue to simply add the new information
67
+ newInstall = matchedAppInfoList .size () == 0 ;
68
+ }
14
69
15
- if (App .packageChangedListener == null ) {
16
- App .packageChangedListener = new App .PackageChangedListener () {
17
- @ Override
18
- public void onPackageChange (AppInfoList appInfoList ) {
19
- appInfoListStore .save (appInfoList );
70
+ if (!Intent .ACTION_PACKAGE_FULLY_REMOVED .equals (action )) {
71
+ Intent launcherIntent = new Intent (Intent .ACTION_MAIN );
72
+ launcherIntent .addCategory (Intent .CATEGORY_LAUNCHER );
73
+ launcherIntent .setPackage (packageName );
74
+ List <ResolveInfo > resolveInfoList = context .getPackageManager ().queryIntentActivities (launcherIntent , 0 );
75
+
76
+ Intent homeIntent = new Intent (Intent .ACTION_MAIN );
77
+ homeIntent .addCategory (Intent .CATEGORY_HOME );
78
+ homeIntent .setPackage (packageName );
79
+ List <ResolveInfo > homeInfoList = context .getPackageManager ().queryIntentActivities (homeIntent , 0 );
80
+
81
+ // If there are no activities that should be displayed on the launcher we can quit here
82
+ if (resolveInfoList .size () == 0 && homeInfoList .size () == 0 ) {
83
+ //Log.d(App.LOG_TAG, "AppInstallOrRemoveReceiver: No launcher Activities"
84
+ // + "\n\tPackage: " + packageName);
85
+ return ;
86
+ }
87
+
88
+ // Deduplicate Resolve Info of activities with both categories - like SearchActivity (see manifest)
89
+ for (ResolveInfo info : resolveInfoList ) {
90
+ Iterator <ResolveInfo > homeIterator = homeInfoList .iterator ();
91
+ while (homeIterator .hasNext ()) {
92
+ ResolveInfo homeInfo = homeIterator .next ();
93
+ if (homeInfo .activityInfo .name .equals (info .activityInfo .name )) {
94
+ homeIterator .remove ();
95
+ break ;
96
+ }
97
+ }
98
+ if (!homeIterator .hasNext ()) {
99
+ break ;
100
+ }
101
+ }
102
+ resolveInfoList .addAll (homeInfoList );
103
+
104
+ /*
105
+ String log =
106
+ "AppInstallOrRemoveReceiver: Updating info:"
107
+ + "\n\tAction: " + action
108
+ + "\n\tPackage: " + packageName
109
+ + "\n\tLabel: " + resolveInfoList.get(0).activityInfo.loadLabel(context.getPackageManager())
110
+ + "\n\tActivities: " + String.valueOf(resolveInfoList.size());
111
+ Log.d(App.LOG_TAG, log);
112
+ Log.d(AppInstallOrRemoveReceiver.LOG_TAG, log);
113
+ for (ResolveInfo i : resolveInfoList) {
114
+ Log.d(App.LOG_TAG, "\t " + i.activityInfo.name);
115
+ Log.d(AppInstallOrRemoveReceiver.LOG_TAG, "\t " + i.activityInfo.name);
116
+ }
117
+ */
118
+
119
+ if (newInstall ) { // New app, simple adding
120
+ for (ResolveInfo info : resolveInfoList ) {
121
+ appInfoList .add (new AppInfo (context , info ));
122
+ }
123
+ } else { // Update, merge data
124
+ for (ResolveInfo info : resolveInfoList ) {
125
+ AppInfo actAppInfo = new AppInfo (context , info );
126
+
127
+ Iterator <AppInfo > oldInfoIterator = matchedAppInfoList .iterator ();
128
+ while (oldInfoIterator .hasNext ()) {
129
+ AppInfo oldInfo = oldInfoIterator .next ();
130
+ if (oldInfo .getActivityName ().equals (actAppInfo .getActivityName ())) {
131
+ if (oldInfo .getLabelMode () == 2 ) { // AppInfo is alias
132
+ oldInfo .setLabel (actAppInfo .getLabel ());
133
+ oldInfo .setInstallTime (actAppInfo .getInstallTime ());
134
+ appInfoList .add (oldInfo );
135
+ } else {
136
+ actAppInfo .setCallCount (oldInfo .getCallCount ());
137
+ actAppInfo .setPinMode (oldInfo .getPinMode ());
138
+ actAppInfo .setLabelMode (oldInfo .getLabelMode ());
139
+ actAppInfo .setOverrideLabel (oldInfo .getOverrideLabel ());
140
+ }
141
+ oldInfoIterator .remove ();
142
+ }
143
+ }
144
+ appInfoList .add (actAppInfo );
20
145
}
21
- };
146
+ }
22
147
}
23
148
24
- new BackgroundGatherAsyncTask (context , appInfoListStore .load ()).execute ();
149
+ if (App .packageChangedListener == null ) {
150
+ appInfoListStore .save (appInfoList );
151
+ } else {
152
+ App .packageChangedListener .onPackageChange (appInfoList );
153
+ }
25
154
}
26
- }
155
+ }
0 commit comments