2012-03-28 12 views
23

Estoy escribiendo una aplicación que permite al usuario ver la lista de aplicaciones instaladas, seleccionar una de ellas y luego iniciarla según lo programado. Utilizando tutoriales de stackoverflow logré descubrir cómo obtener una lista de las actividades instaladas, sus nombres de paquetes e íconos (es decir, here - varias formas de hacerlo). Por si acaso, así es como empiezo actividades, funciona perfectamente, no hay problema aquí:Android: Cómo obtener una lista de actividades instaladas, tal como aparecen en el iniciador, sin duplicados

Intent launchIntent = packageManager.getLaunchIntentForPackage(packageName); 
launchIntent.setAction(Intent.ACTION_MAIN); 
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); 
launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(launchIntent); 

El problema es con la recuperación de una lista de aplicaciones instaladas. He encontrado dos formas de obtener una lista de aplicaciones instaladas:

1) el uso

PackageManager pm = getPackageManager(); 
List<ApplicationInfo> apps = pm.getInstalledApplication(PackageManager.GET_META_DATA) 

y desde cada elemento de apps, usted puede obtener es el nombre del paquete y la etiqueta del envase (nombres de aplicaciones).

2) el uso

PackageManager pm = getPackageManager();  
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); 
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 
List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(mainIntent, 0); 
for(ResolveInfo info : resolveInfos) { 
    ApplicationInfo applicationInfo = info.activityInfo.applicationInfo; 
    //... 
    //get package name, icon and label from applicationInfo object  
} 

Hay un problema con primera método: devuelve todos los paquetes instalados, incluyendo los servicios del sistema, que pueden no contienen ninguna actividad y por lo tanto no son launchable. Aquí hay una captura de pantalla con un ejemplo: app list with packages

Todos los elementos anteriores que no tienen iconos no se pueden abrir.

Hay un problema con el enfoque segundo así: Varios elementos de la lista tienen duplicados: app list with duplicates

Al configurar un punto de interrupción en el depurador que veo, que estos elementos "Mapas" tienen diferentes nombres de actividad ("com.google.android.maps.MapsActivity", "com.google.android.maps.LatitudeActivity", "com.google.android.maps.PlacesActivity", etc.).

Decidí usar el segundo enfoque, porque da una lista que es más adecuada para mis necesidades, pero no puedo encontrar una forma de filtrar los duplicados y solo mostrar la actividad predeterminada para la aplicación, ya que aparecer en el Iniciador (solo ve un 'Mapas' en la lista de aplicaciones de su teléfono, no cuatro). Intenté filtrar las aplicaciones del sistema a través del ApplicationInfo.FLAG_SYSTEM, pero esto elimina muchas aplicaciones que quiero tener, incluidos Maps y otras aplicaciones preinstaladas. Intenté usar el indicador PackageManager.MATCH_DEFAULT_ONLY al ejecutar queryIntentActivities, pero esto también filtra muchas aplicaciones, dejando solo algunas.

Estoy un poco perdido aquí, y no sé qué hacer. He leído todas las preguntas sobre stackoverflow sobre cómo recuperar una lista de aplicaciones instaladas, pero este problema nunca se ha planteado. Por favor, ayuda a alguien? ¿Cómo recupero una lista de aplicaciones iniciables instaladas que no tiene duplicados?

+0

Usted dice que "este tema nunca ha sido criado". Por favor revise esto, tal vez esto ayude: http://stackoverflow.com/questions/4598769/list-of-user-installed-apps/4599124#4599124 – Zelimir

+1

Quise decir duplicados en la lista, no he visto a nadie mencionar esto. Sí, he visto ese comentario, he intentado omitir aplicaciones con 'ApplicationInfo.FLAG_SYSTEM', pero por alguna razón esto elimina muchas aplicaciones válidas, incluidos juegos y tal. –

Respuesta

13
Intent localIntent2 = new Intent("android.intent.action.PICK_ACTIVITY"); 
Intent localIntent3 = new Intent("android.intent.action.MAIN",null); 
localIntent3.addCategory("android.intent.category.LAUNCHER"); 
localIntent2.putExtra("android.intent.extra.INTENT",localIntent3); 
startActivityForResult(localIntent2, 1); 

probar este código. Enumerará solo las aplicaciones que están todas instaladas en su dispositivo.

+0

Sí, funcionó! ¡Gracias! –

+0

funciona, pero esto será más efectivo si puede ejecutar la aplicación seleccionada. Porque a partir de ahora cuando seleccionas una aplicación, no pasó nada. –

+1

buena respuesta, pero evite utilizar cadenas codificadas, en su lugar use constantes, como Intent.EXTRA_INTENT para "android.intent.extra.INTENT". –

6

Pruebe el código a continuación y avíseme qué sucedió.

PackageManager manager = getPackageManager(); 
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); 
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 

List<ResolveInfo> resolveInfos= manager.queryIntentActivities(mainIntent, 0); 
// Below line is new code i added to your code 
Collections.sort(resolveInfos, new ResolveInfo.DisplayNameComparator(manager)); 

for(ResolveInfo info : resolveInfos) { 
    ApplicationInfo applicationInfo = info.activityInfo.applicationInfo; 
    //... 
    //get package name, icon and label from applicationInfo object  
} 
+0

Hola, aquí hay una captura de pantalla de lo que sucedió: http://i.stack.imgur.com/xCXqY.png Todavía hay 4 'Mapas' en la lista, pero ahora están en orden aleatorio. –

13

Podría llegar tarde, pero acabo de encontrar una forma perfecta de que todas las aplicaciones que tienen el iniciador & no tengan aplicaciones duplicadas (incluidas las aplicaciones del sistema, como contactos, mapas, etc.). Aunque, la respuesta de Satheesh podría estar funcionando (no me he controlado), pero quería elegir varias actividades, así que usé el código siguiente para instalar las aplicaciones.

Utilicé su segundo enfoque y descarté paquetes duplicados usando HashSet. Aquí está el código final:

final PackageManager packageManager = getPackageManager(); 
    Intent intent = new Intent(Intent.ACTION_MAIN, null); 
    intent.addCategory(Intent.CATEGORY_LAUNCHER); 
    List<ResolveInfo> resInfos = packageManager.queryIntentActivities(intent, 0); 
    //using hashset so that there will be no duplicate packages, 
    //if no duplicate packages then there will be no duplicate apps 
    HashSet<String> packageNames = new HashSet<String>(0); 
    List<ApplicationInfo> appInfos = new ArrayList<ApplicationInfo>(0); 

    //getting package names and adding them to the hashset 
    for(ResolveInfo resolveInfo : resInfos) { 
     packageNames.add(resolveInfo.activityInfo.packageName); 
    } 

    //now we have unique packages in the hashset, so get their application infos 
    //and add them to the arraylist 
    for(String packageName : packageNames) { 
     try { 
      appInfos.add(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)); 
     } catch (NameNotFoundException e) { 
      //Do Nothing 
     } 
    } 

    //to sort the list of apps by their names 
    Collections.sort(appInfos, new ApplicationInfo.DisplayNameComparator(packageManager)); 
3

que tenían el mismo requisito. Finalmente agregué otra condición para filtrar la lista de aplicaciones. Acabo de comprobar si la aplicación tiene "intención de iniciador".

Por lo tanto, el código resultante se parece a ...

PackageManager pm = getPackageManager(); 
List<ApplicationInfo> apps = pm.getInstalledApplications(PackageManager.GET_GIDS); 

for (ApplicationInfo app : apps) { 
    if(pm.getLaunchIntentForPackage(app.packageName) != null) { 
     // apps with launcher intent 
     if((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 1) { 
      // updated system apps 
     } else if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 1) { 
      // system apps 
     } else { 
      // user installed apps 
     } 
     appsList.add(app); 
    } 

} 
1

Tanto @Ashish Tanna y jozze tienen razón, pero el rendimiento tal vez un pequeño problema.

Este es el mejor rendimiento.

Set<String> packageNameSet = new HashSet<>(); 
PackageManager pm = context.getPackageManager(); 
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); 
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 
List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(mainIntent, 0); 
for(ResolveInfo info : resolveInfos) { 
    // be added 
    ApplicationInfo applicationInfo; 
    if (info == null || (applicationInfo = info.activityInfo.applicationInfo) == null 
      || !applicationInfo.enabled || packageNameSet.contains(applicationInfo.packageName)) { 
     continue; 
    } 
    packageNameSet.add(applicationInfo.packageName); 

    //... 
    //get package name, icon and label from applicationInfo object 
} 

(1) Añadir un HashSet (2) Juzgar si la aplicación está habilitada (3) si el juez tiene en su interior el hashset

Cuestiones relacionadas