美文网首页
Android 获取应用列表

Android 获取应用列表

作者: 未子涵 | 来源:发表于2020-06-18 21:00 被阅读0次

    前言

    目前正是Android 11 马上要发布的时期,当前在Android手机上获取应用安装列表,要从三个维度上区分:获取方法、系统版本、是否系统应用。

    • 获取方法:至少有两种方法,它们的行为结果会有所差异
    • 系统版本:从 Android 11 开始,应用列表的获取将受到限制
    • 是否系统应用:系统应用与非系统应用的获取结果,也不尽相同

    获取方法介绍

    获取所有应用列表(系统应用+非系统应用),常用的方法有2种:Shell命令行、系统API。

    而要进一步区分是否系统应用,只要对上述结果进行一次过滤即可。下面分别介绍:

    1.shell命令行

    pm list packages
    

    示例代码:

    private List<String> getPkgList() {
        List<String> packages = new ArrayList<String>();
        try {
            Process p = Runtime.getRuntime().exec("pm list packages");
            InputStreamReader isr = new InputStreamReader(p.getInputStream(), "utf-8");
            BufferedReader br = new BufferedReader(isr);
            String line = br.readLine();
            while (line != null) {
                line = line.trim();
                if (line.length() > 8) {
                    String prefix = line.substring(0, 8);
                    if (prefix.equalsIgnoreCase("package:")) {
                        line = line.substring(8).trim();
                        if (!TextUtils.isEmpty(line)) {
                            packages.add(line);
                        }
                    }
                }
                line = br.readLine();
            }
            br.close();
            p.destroy();
        } catch (Throwable t) {
            t.printStacktraces();
        }
        return packages;
    }
    

    2.系统API

    PackageManager.getInstalledPackages()
    

    示例代码:

    private List<String> getPkgListNew() {
        List<String> packages = new ArrayList<String>();
        try {
            List<PackageInfo> packageInfos = context.getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES |
                    PackageManager.GET_SERVICES);
            for (PackageInfo info : packageInfos) {
                String pkg = info.packageName;
                packages.add(pkg);
            }
        } catch (Throwable t) {
            t.printStackTrace();;
        }
        return packages;
    }
    

    判断是否系统应用

    // 通过packName得到PackageInfo,作为参数传入即可
    private boolean isSystemApp(PackageInfo pi) {
        boolean isSysApp = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1;
        boolean isSysUpd = (pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 1;
        return isSysApp || isSysUpd;
    }
    

    总结对比

    • 测试机:Google Pixel 3 XL
    • 系统应用:262个
    • 非系统应用:2个(包括测试demo)

    说明:

    • 这里说的权限是:QUERY_ALL_PACKAGES,Android 11 新增权限,不用动态申请
    • 这里说的 >= Android 11 是:targetSdkVersion 为 Android 11 且 运行在11的设备上

    补充:广播监听应用安装/卸载的行为变化

    如果使用了广播,监听应用安装与卸载动作,那么在 Android 11 上也有一些行为变化。

    概括来讲,就是 Android 11 下,若无 QUERY_ALL_PACKAGES 权限,则无法监听到 安装 动作

    Android 11 之前
    • 能监听到 安装/卸载
    Android 11 开始
    • 若无 QUERY_ALL_PACKAGES 权限:只能监听到 卸载
    • 若有 QUERY_ALL_PACKAGES 权限:仍能监听到 安装/卸载

    相关文章

      网友评论

          本文标题:Android 获取应用列表

          本文链接:https://www.haomeiwen.com/subject/twjpxktx.html