解决Android11(API 30)之后,默认无法获取设备已安装的全部应用的问题

一. 原因

详解参考官方文档:Android 上的软件包可见性过滤  |  Android Developers (google.cn)

简单来说就是,为了用户数据的隐私考虑,默认不允许当前应用访问到全部应用信息,而是访问系统过滤后的应用信息,这也就导致了我们无法只通过 packageManager.getInstalledApplications()方法、packageManager.getInstalledPackages()方法来获取设备的全部应用列表。

二. 解决方法

(一)若想在设备中查询是否包含特定的应用:

1.在manifest中直接声明需访问到的应用,格式如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <queries>
        <!-- 想查询访问的应用包名 如:淘宝 -->
        <package android:name="com.taobao.taobao" />
    </queries>

...
...
</manifest>
声明后,本应用则会和声明要访问的这个应用彼此可见,因而之后可访问得到。
2.获取应用信息
        PackageManager packageManager = getPackageManager();
        //获取过滤后的已安装应用信息,若在清单中声明的应用存在,则系统不会将其过滤掉
        List<PackageInfo> installedPackages = packageManager.getInstalledPackages(0);
        //创建一个集合用于存储已安装APP的包名
        List<String> installedAppNames = new ArrayList<>();
        //遍历获取已安装的应用包名
        for (int i = 0; i < installedPackages.size(); i++) {
            installedAppNames.add(installedPackages.get(i).packageName);
            LogUtils.d(this,"AppName-->" + installedAppNames.get(i));
        }
        //判断是否包含我们所需的应用包名
        mHasTaoBaoApp = installedAppNames.contains("com.taobao.taobao");

        PackageManager packageManager = getPackageManager();
        try {
                PackageInfo packageInfo = packageManager.getPackageInfo("com.taobao.taobao",         PackageManager.MATCH_UNINSTALLED_PACKAGES);
            if (packageInfo != null) {
                mHasTaoBaoApp = true;//有淘宝
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            mHasTaoBaoApp = false;//没有淘宝
        }