18
18
import android .content .Context ;
19
19
import android .content .Intent ;
20
20
import android .app .ActivityOptions ;
21
+ import android .content .pm .ActivityInfo ;
22
+ import android .content .pm .ApplicationInfo ;
21
23
import android .content .pm .PackageManager ;
22
24
import android .content .pm .ResolveInfo ;
23
25
import android .content .res .Configuration ;
@@ -244,8 +246,7 @@ public static void startApp(Intent launchIntent, int displayId, boolean forceSto
244
246
@ SuppressLint ("QueryPermissionsNeeded" )
245
247
public static List <ResolveInfo > getDrawerApps () {
246
248
Context context = FakeContext .get ();
247
- PackageManager packageManager = context .getPackageManager ();
248
-
249
+ PackageManager pm = context .getPackageManager ();
249
250
Intent intent = new Intent (Intent .ACTION_MAIN , null );
250
251
251
252
UiModeManager uiModeManager = (UiModeManager ) context .getSystemService (Context .UI_MODE_SERVICE );
@@ -254,66 +255,154 @@ public static List<ResolveInfo> getDrawerApps() {
254
255
} else {
255
256
intent .addCategory (Intent .CATEGORY_LAUNCHER );
256
257
}
257
- return packageManager .queryIntentActivities (intent , 0 );
258
+ return pm .queryIntentActivities (intent , 0 );
258
259
}
259
260
260
- public static Intent getAppWithUniqueLabel (List <ResolveInfo > drawerApps , String label ){
261
- String errorMessage = "No unique app found named \" " + label + "\" \n " ;
261
+ public static Intent getIntentFromAppDrawer (String query , boolean isPackageName ){
262
+ String errorMessage = isPackageName ?
263
+ "No launchable app with package name \" " + query + "\" found from app drawer" :
264
+ "No unique launchable app named \" " + query + "\" found from app drawer" ;
265
+ String orgQuery = query ;
266
+ query = query .toLowerCase (Locale .getDefault ());
267
+
268
+ List <ResolveInfo > exactMatchesLabel = new ArrayList <>();
269
+ List <ResolveInfo > potentialMatchesAppName = new ArrayList <>();
270
+ List <ResolveInfo > potentialMatchesPkgName = new ArrayList <>();
262
271
Context context = FakeContext .get ();
263
- label = label .toLowerCase (Locale .getDefault ());
264
-
265
- List <ResolveInfo > exactMatches = new ArrayList <>();
266
- List <ResolveInfo > potentialMatches = new ArrayList <>();
267
-
268
- for (ResolveInfo drawerApp : drawerApps ) {
269
- String appName = drawerApp .loadLabel (context .getPackageManager ()).toString ();
270
- if (appName .toLowerCase (Locale .getDefault ()).equals (label )){
271
- exactMatches .add (drawerApp );
272
- }else if (appName .toLowerCase (Locale .getDefault ())
273
- .contains (label .toLowerCase (Locale .getDefault ()))) {
274
- potentialMatches .add (drawerApp );
272
+ PackageManager pm = context .getPackageManager ();
273
+
274
+ for (ResolveInfo drawerApp : getDrawerApps ()) {
275
+ String packageName = drawerApp .activityInfo .packageName ;
276
+ String label = drawerApp .loadLabel (pm ).toString ().toLowerCase (Locale .getDefault ());
277
+
278
+ if (isPackageName ){
279
+ if (packageName .equals (query )) {
280
+ ComponentName componentName = new ComponentName (packageName , drawerApp .activityInfo .name );
281
+ return new Intent ().setComponent (componentName )
282
+ .putExtra ("APP_LABEL" , drawerApp .loadLabel (pm ).toString ());
283
+ } else if (packageName .contains (query )){
284
+ potentialMatchesPkgName .add (drawerApp );
285
+ }
286
+ } else {
287
+ if (label .equals (query )) {
288
+ exactMatchesLabel .add (drawerApp );
289
+ } else if (label .contains (query )){
290
+ potentialMatchesAppName .add (drawerApp );
291
+ }
275
292
}
276
293
}
277
294
278
- if (exactMatches .size () == 1 ){
279
- ComponentName componentName = new ComponentName (exactMatches .get (0 ).activityInfo .packageName , exactMatches .get (0 ).activityInfo .name );
280
- return new Intent ().setComponent (componentName )
281
- .putExtra ("APP_LABEL" , exactMatches .get (0 ).loadLabel (context .getPackageManager ()).toString ());
282
- } else {
283
- String suggestions = "" ;
295
+ Intent launchIntent = processResolvedLists (pm ,isPackageName ,false ,errorMessage ,exactMatchesLabel ,potentialMatchesAppName ,potentialMatchesPkgName );
284
296
285
- if (!exactMatches .isEmpty ()){
286
- suggestions +=LogUtils .buildAppListMessage ("Found " +exactMatches .size ()+" exact matches:" ,exactMatches )+"\n " ;
287
- }
288
- if (!potentialMatches .isEmpty ()){
289
- suggestions +=LogUtils .buildAppListMessage ("Found " + potentialMatches .size () + " potential " + (potentialMatches .size () == 1 ? "match:" : "matches:" ), potentialMatches )+"\n " ;
290
- }
297
+ if (launchIntent == null ){
298
+ Ln .w ("Trying to find from list of all apps" );
299
+ return getIntentFromListOfAllApps (orgQuery ,isPackageName );
300
+ }
301
+ else if (launchIntent .getBooleanExtra ("MULTIPLE_EXACT_LABELS" , false )) {
302
+ //Let processResolvedLists() return a "garbage" intent if there are multiple exact labels.
303
+ // We want to avoid redundant check. This happens if first check "launchIntent == null"
304
+ // becomes true since getIntentFromListOfAllApps() also calls processResolvedLists().
305
+ // This limitation can be removed
306
+ return null ;
307
+ }
308
+ return launchIntent ;
309
+ }
310
+
311
+ @ SuppressLint ("QueryPermissionsNeeded" )
312
+ public static Intent getIntentFromListOfAllApps (String query , boolean isPackageName ){
313
+ String errorMessage = isPackageName ?
314
+ "No launchable app with package name \" " + query + "\" found from list of all apps" :
315
+ "No unique launchable app named \" " + query + "\" found from list of all apps" ;
316
+ query = query .toLowerCase (Locale .getDefault ());
317
+
318
+ List <ResolveInfo > exactMatchesLabel = new ArrayList <>();
319
+ List <ResolveInfo > potentialMatchesAppName = new ArrayList <>();
320
+ List <ResolveInfo > potentialMatchesPkgName = new ArrayList <>();
321
+ Context context = FakeContext .get ();
322
+ PackageManager pm = context .getPackageManager ();
323
+ ResolveInfo resolveInfo ;
324
+
325
+ boolean isTV = false ;
326
+ UiModeManager uiModeManager = (UiModeManager ) context .getSystemService (Context .UI_MODE_SERVICE );
327
+ if (uiModeManager .getCurrentModeType () == Configuration .UI_MODE_TYPE_TELEVISION ) {
328
+ isTV = true ;
329
+ }
291
330
292
- if (!suggestions .isEmpty ()){
293
- Ln .e (errorMessage +suggestions );
331
+ for (ApplicationInfo appInfo : pm .getInstalledApplications (PackageManager .GET_META_DATA )) {
332
+ String packageName = appInfo .packageName ;
333
+ String label = appInfo .loadLabel (pm ).toString ().toLowerCase (Locale .getDefault ());
334
+ Intent launchIntent = isTV ?
335
+ pm .getLeanbackLaunchIntentForPackage (packageName ) :
336
+ pm .getLaunchIntentForPackage (packageName );
337
+
338
+ if (isPackageName ){
339
+ if (packageName .equals (query ) && launchIntent == null ) {
340
+ Ln .e ("No launch intent for " + appInfo .loadLabel (pm ) + " [" +packageName +"]" );
341
+ return null ;
342
+ } else if (packageName .equals (query )) {
343
+ return launchIntent .putExtra ("APP_LABEL" , label );
344
+ }else if (packageName .contains (query ) && launchIntent != null ){
345
+ resolveInfo = pm .resolveActivity (launchIntent , 0 );
346
+ potentialMatchesPkgName .add (resolveInfo );
347
+ }
348
+ } else {
349
+ if (launchIntent == null ) {
350
+ if (label .equals (query )){
351
+ Ln .w ("Ignoring " + appInfo .loadLabel (pm ) + " [" +packageName +"] which has no launch intent" );
352
+ }
353
+ continue ;
354
+ }
355
+ resolveInfo = pm .resolveActivity (launchIntent , 0 );
356
+ if (label .equals (query )) {
357
+ exactMatchesLabel .add (resolveInfo );
358
+ } else if (label .contains (query )){
359
+ potentialMatchesAppName .add (resolveInfo );
360
+ }
294
361
}
295
- return null ;
296
362
}
363
+
364
+ return processResolvedLists (pm ,isPackageName ,true ,errorMessage ,exactMatchesLabel ,potentialMatchesAppName ,potentialMatchesPkgName );
297
365
}
298
366
299
- public static Intent getAppGivenPackageName (List <ResolveInfo > drawerApps , String packageName ){
300
- packageName = packageName .toLowerCase (Locale .getDefault ());
301
- String errorMessage = "No app found with package name \" " + packageName + "\" \n " ;
302
- List <ResolveInfo > potentialMatches = new ArrayList <>();
303
- for (ResolveInfo drawerApp : drawerApps ) {
304
- if (drawerApp .activityInfo .packageName .equals (packageName )){
305
- ComponentName componentName = new ComponentName (drawerApp .activityInfo .packageName , drawerApp .activityInfo .name );
306
- return new Intent ().setComponent (componentName );
307
- } else if (drawerApp .activityInfo .packageName
308
- .contains (packageName )) {
309
- potentialMatches .add (drawerApp );
367
+ private static Intent processResolvedLists (PackageManager pm , boolean isPackageName , boolean showSuggestions , String errorMessage ,
368
+ List <ResolveInfo > exactMatchesLabel ,
369
+ List <ResolveInfo > potentialMatchesAppName ,
370
+ List <ResolveInfo > potentialMatchesPkgName ){
371
+ String suggestions = "\n " ;
372
+ boolean multipleExactLabelMatches = false ;
373
+ if (isPackageName ){
374
+ if (!potentialMatchesPkgName .isEmpty ()){
375
+ suggestions +=LogUtils .buildAppListMessage ("Found " +potentialMatchesPkgName .size ()+" potential matches:" ,potentialMatchesPkgName );
376
+ }
377
+ } else {
378
+ if (exactMatchesLabel .size () == 1 ){
379
+ ActivityInfo activityInfo = exactMatchesLabel .get (0 ).activityInfo ;
380
+ ComponentName componentName = new ComponentName (activityInfo .packageName , activityInfo .name );
381
+ return new Intent ().setComponent (componentName )
382
+ .putExtra ("APP_LABEL" , exactMatchesLabel .get (0 ).loadLabel (pm ).toString ());
383
+ } else {
384
+ if (!exactMatchesLabel .isEmpty ()){
385
+ multipleExactLabelMatches = true ;
386
+ showSuggestions = true ;
387
+ suggestions +=LogUtils .buildAppListMessage ("Found " +exactMatchesLabel .size ()+" exact matches:" ,exactMatchesLabel )+"\n " ;
388
+ }
389
+ if (!potentialMatchesAppName .isEmpty ()){
390
+ suggestions +=LogUtils .buildAppListMessage ("Found " + potentialMatchesAppName .size () + " other potential " + (potentialMatchesAppName .size () == 1 ? "match:" : "matches:" ), potentialMatchesAppName )+"\n " ;
391
+ }
310
392
}
311
393
}
312
- if (!potentialMatches .isEmpty ()){
313
- Ln .e (errorMessage +LogUtils .buildAppListMessage ("Found " + potentialMatches .size () + " potential " + (potentialMatches .size () == 1 ? "match:" : "matches:" ), potentialMatches ));
394
+
395
+ if (showSuggestions ){
396
+ Ln .e (errorMessage + (suggestions .equals ("\n " )? "\0 " : suggestions ));
314
397
} else {
315
398
Ln .e (errorMessage );
316
399
}
317
- return null ;
400
+ if (multipleExactLabelMatches ){
401
+ return new Intent ().putExtra ("MULTIPLE_EXACT_LABELS" , true );
402
+ } else {
403
+ return null ;
404
+ }
318
405
}
319
406
}
407
+
408
+
0 commit comments