如何获取已安装的Android应用程序列表并选择其中一个运行

365

本周早些时候我提出了一个类似的问题,但我仍然不明白如何获取所有已安装应用程序的列表,然后选择其中一个运行。

我尝试过:

Intent intent = new Intent(ACTION_MAIN);
intent.addCategory(CATEGORY_LAUNCHER);

这只显示预安装或可以运行 ACTION_MAIN Intent 类型的应用程序。

我还知道我可以使用 PackageManager 获取所有已安装的应用程序,但是如何使用它来运行特定的应用程序呢?


你如何只获取列表中选择的应用程序的信息? - Pedrum
你是想要启动一组特定的应用程序,比如相册应用程序?还是一组可以为您提供服务的应用程序,比如获取文件? - Ahmad Sattout
23个回答

466

以下是使用PackageManager更简洁的方法

final PackageManager pm = getPackageManager();
//get a list of installed apps.
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);

for (ApplicationInfo packageInfo : packages) {
    Log.d(TAG, "Installed package :" + packageInfo.packageName);
    Log.d(TAG, "Source dir : " + packageInfo.sourceDir);
    Log.d(TAG, "Launch Activity :" + pm.getLaunchIntentForPackage(packageInfo.packageName)); 
}
// the getLaunchIntentForPackage returns an intent that you can use with startActivity() 

更多信息请访问 http://qtcstation.com/2011/02/how-to-launch-another-app-from-your-app/


请确保您没有过滤掉调试日志语句。 - QED
这段代码能够正常工作,但是你有没有想过如何将这些应用程序列表放入 ListView 中呢? - androidBoomer
1
@DavidT。我已经解决了。现在,我正在研究如何访问那些已安装的应用程序,以便在我的应用程序内创建快捷方式。这可能吗? - androidBoomer
@androidBoomer,我也这么认为。你应该能够获取每个应用程序的图标,然后根据它们指定接受的意图启动它们。你可以提出问题并标记我来回答。我在这里(评论区)没有太多空间来回答。 - David T.
@DavidT. 这是我的问题。我真的需要你的帮助。http://stackoverflow.com/questions/21371491/create-app-shortcut-inside-the-custom-launcher-in-android - androidBoomer
显示剩余9条评论

294

以下是获取安装在Android设备上的活动/应用程序列表的代码:

Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> pkgAppsList = context.getPackageManager().queryIntentActivities( mainIntent, 0);

您可以在ResolveInfo中获取所有必要的数据来启动应用程序。您可以在此处查看 ResolveInfo javadoc。


3
我该如何开始其中之一?我得到了ResolveInfo中的activityInfo,但我无法将其启动。 - Spidey
2
算了,我找到了。我应该使用完整的类名(包括包名和类名)创建一个新的Intent。 - Spidey
1
你如何只获取列表中选定应用程序的信息? - Pedrum
1
我想了解 Android/Play Store 政策,关于我的应用程序读取和存储所有应用程序列表并潜在地与服务器通信。是否有任何指南? - dowjones123
2
@dowjones123 你有找到关于这个的指南吗? - RmK
显示剩余5条评论

67

过滤系统应用的另一种方法(适用于king9981的示例):

/**
 * Return whether the given PackageInfo represents a system package or not.
 * User-installed packages (Market or otherwise) should not be denoted as
 * system packages.
 * 
 * @param pkgInfo
 * @return
 */
private boolean isSystemPackage(PackageInfo pkgInfo) {
    return ((pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
}

4
这是过滤系统应用程序的最佳答案。 - Bjorn
5
但是它可以过滤应用程序,例如设置、地图等,如何将它们列出来? - Ata
8
你的返回语句中的"? true : false"部分是多余的。 - k2col
简化返回 ((pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0); - Bhavesh Rangani
如何过滤付费应用? - Pemba Tamang
显示剩余4条评论

63

这里有一个很好的例子:

class PInfo {
    private String appname = "";
    private String pname = "";
    private String versionName = "";
    private int versionCode = 0;
    private Drawable icon;
    private void prettyPrint() {
        Log.v(appname + "\t" + pname + "\t" + versionName + "\t" + versionCode);
    }
}

private ArrayList<PInfo> getPackages() {
    ArrayList<PInfo> apps = getInstalledApps(false); /* false = no system packages */
    final int max = apps.size();
    for (int i=0; i<max; i++) {
        apps.get(i).prettyPrint();
    }
    return apps;
}

private ArrayList<PInfo> getInstalledApps(boolean getSysPackages) {
    ArrayList<PInfo> res = new ArrayList<PInfo>();        
    List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
    for(int i=0;i<packs.size();i++) {
        PackageInfo p = packs.get(i);
        if ((!getSysPackages) && (p.versionName == null)) {
            continue ;
        }
        PInfo newInfo = new PInfo();
        newInfo.appname = p.applicationInfo.loadLabel(getPackageManager()).toString();
        newInfo.pname = p.packageName;
        newInfo.versionName = p.versionName;
        newInfo.versionCode = p.versionCode;
        newInfo.icon = p.applicationInfo.loadIcon(getPackageManager());
        res.add(newInfo);
    }
    return res; 
}

1
如果需要执行其中一个,你该怎么做?我的意思是,你能获取到Intent吗? - Ton
太好了。感谢您的回答。我已经在我的应用程序中使用了您的答案,但是我遇到了一个小问题,就是图标的大小。大多数图标都是正常的,但有些图标非常大或非常小。我该如何解决这个问题?您有什么想法吗?谢谢。 - Meysam Valueian

42

获取已安装的非系统应用列表

public static void installedApps()
{
    List<PackageInfo> packList = getPackageManager().getInstalledPackages(0);
    for (int i=0; i < packList.size(); i++)
    {
        PackageInfo packInfo = packList.get(i);
        if (  (packInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)
        {
            String appName = packInfo.applicationInfo.loadLabel(getPackageManager()).toString();
            Log.e("App № " + Integer.toString(i), appName);
        }
    }
}

21

要过滤基于系统的应用程序:

private boolean isSystemPackage(ResolveInfo ri) {
    return (ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}

19

您可以使用“PackageManager”获取所有已安装的应用程序。

List<PackageInfo> apps = getPackageManager().getInstalledPackages(0);

要运行一个应用程序,您可以使用其软件包名称

Intent launchApp = getPackageManager().getLaunchIntentForPackage(“package name”)
startActivity(launchApp);

如果您需要更详细的信息,可以阅读这篇博客http://codebucket.co.in/android-get-list-of-all-installed-apps/


这更加切题了。我们可以通过找到所需的应用程序来设置适当的检查。 - Noman

17

context.getPackageManager().getInstalledApplications(PackageManager.GET_META_DATA);

应该返回所有已安装的应用程序列表,但是在 Android 11 中,它只返回系统应用程序列表。为了获取所有应用程序(系统+用户)的列表,我们需要向应用程序提供一个额外的权限,即:

<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>


3
小修正: <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> 翻译: <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> 表示“请求查询所有应用程序包”的权限。 - FrankKrumnow

15
你可以通过以下代码在Android设备中查找已安装的应用程序列表,“packageInfo”包含设备上安装的应用程序信息。我们可以从packageinfo对象检索安装的应用程序的Intent,并使用startactivity(intent)启动应用程序。你可以自行决定如何组织UI,无论是ListView还是GridView。因此,在基于位置的单击事件上,您可以检索意图对象并启动活动意图。
final PackageManager pm = getPackageManager();

List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);


for (ApplicationInfo packageInfo : packages) 

{
 if(pm.getLaunchIntentForPackage(packageInfo.packageName)!= null &&   

                   !pm.getLaunchIntentForPackage(packageInfo.packageName).equals(""))


{

    System.out.println("Package Name :" + packageInfo.packageName);

    System.out.println("Launch Intent For Package :"   +  
                  pm.getLaunchIntentForPackage(packageInfo.packageName));

    System.out.println("Application Label :"   + pm.getApplicationLabel(packageInfo));

    System.out.println("Application Label :"   + 
                           pm.getApplicationIcon(packageInfo.packageName).toString());

    System.out.println("i : "+i);

    /*if(i==2)

    {
         startActivity(pm.getLaunchIntentForPackage(packageInfo.packageName));

     break;

    }*/

    i++;

}
}

13

我有一个要求,需要过滤掉用户实际上不使用的系统应用程序(例如"com.qualcomm.service", "update services"等)。最终,我添加了另一个条件来筛选应用列表。我只检查该应用是否具有'launcher intent'。

因此,最终的代码看起来像...

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) != 0) {
                    // updated system apps

                } else if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                    // system apps

                } else {
                    // user installed apps

                }
                appsList.add(app);
            }

        }

谢谢。getLaunchIntentForPackage非常有用,可以获取应用程序抽屉中存在的应用程序 :-) - Gabriel Hautclocq

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接