我正在编写一个应用程序,允许用户查看已安装的应用程序列表,选择其中一个,然后按计划启动它。使用stackoverflow中的教程,我设法弄清楚如何获取已安装活动的列表,它们的包名称和图标(即here - 有几种方法可以实现)。以防万一,这就是我开始活动的方式,它完美无瑕,没问题:
Intent launchIntent = packageManager.getLaunchIntentForPackage(packageName);
launchIntent.setAction(Intent.ACTION_MAIN);
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(launchIntent);
问题在于检索已安装的应用列表。我找到了两种获取已安装应用程序列表的方法:
1)使用
PackageManager pm = getPackageManager();
List<ApplicationInfo> apps = pm.getInstalledApplication(PackageManager.GET_META_DATA)
从apps
的每个元素中,您都可以获得它的包名和包标签(应用名称)。
2)使用
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
}
第一个方法存在问题:它返回所有已安装的软件包,包括系统服务,这些软件包可能不包含任何活动,因此无法启动。这是一个带有示例的屏幕截图:
上面没有图标的所有项目都无法启动。
第二方法也存在问题:列表中的多个项目都有重复项:
当我在调试器中设置断点时,我看到这些“地图”项目具有不同的活动名称(“com.google.android.maps.MapsActivity”,“com.google.android.maps.LatitudeActivity”,“ com.google.android.maps.PlacesActivity“等)。
我决定使用第二种方法,因为它提供了一个更适合我需要的列表,但我找不到一种方法来过滤掉重复项,只显示应用程序的默认活动,因为它们出现在启动器中(您只能在手机的应用列表中看到一个“地图”,而不是四个)。我尝试通过ApplicationInfo.FLAG_SYSTEM
过滤出系统应用,但这会删除我想要的许多应用,包括地图和其他预装的应用。我在执行queryIntentActivities时尝试使用PackageManager.MATCH_DEFAULT_ONLY
标志,但这也会过滤掉许多应用,只留下一些。
我有点迷失在这里,我不知道该怎么做。我已经阅读了关于检索已安装应用列表的stackoverflow的所有问题,但这个问题从未提出过。请帮助任何人?如何检索没有重复项的已安装可启动应用程序列表?
答案 0 :(得分:14)
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);
试试这段代码。它将仅列出设备中安装的所有应用程序。
答案 1 :(得分:14)
我可能会迟到,但我发现了一个让所有应用都拥有启动器和放大器的完美方式。没有重复的应用程序(包括联系人,地图等系统应用程序)。 虽然,Satheesh的答案可能有效(但没有检查过我自己),但我想选择多个活动,所以我使用下面的代码来安装应用程序。
我使用了第二种方法并使用HashSet丢弃了重复的包。 这是最终的代码:
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));
答案 2 :(得分:6)
尝试下面的代码,让我知道发生了什么。
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
}
答案 3 :(得分:3)
我有同样的要求。最后,我添加了另一个条件来过滤应用列表。我刚检查了该应用是否具有'启动器意图'。
因此,结果代码看起来像......
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);
}
}
答案 4 :(得分:2)
@Ashish Tanna和jozze都是对的,但性能可能有点问题。
这是性能最佳的。
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)添加一个HashSet (2)判断是否启用了应用程序 (3)判断是否在hashset内部