使用 PackageManager 不会在 Android 11 上填充应用列表

Nx *_*tic 4 java android list android-studio

我正在使用包管理器来获取启动器中应用程序抽屉界面的应用程序列表。一切正常,但在 Android 11 上,唯一显示的应用程序是 Android 设置应用程序。是什么改变了它不再工作和/或我应该做什么才能使它工作?应用程序列表现在基于用户配置文件吗?

这是我当前的列表代码

public static List<ApplicationInfo> getPrimaryApps(Context context) {    
    PackageManager pm = context.getPackageManager();    
    List<ApplicationInfo> res = new ArrayList<>();    
    ArrayList<String> hiddenPackages = new ArrayList<>();    
    IconPackHelper iconPackHelper = IconPackHelper.getInstance(context);

    //All Apps Package Filter    
    Set<String> filteredPackages = new HashSet<>();

    filteredPackages.add("com.android.wallpaper.livepicker");    
    filteredPackages.add("com.gocalsd.symphlyx");

    //All Apps Blacklist    
    String[] flattenedPackages = SettingsProvider.get(context).getString(SettingsProvider.HIDDEN_APPS, "").split("\\|");

    for (String flat : flattenedPackages) {    
        ComponentName cmp = ComponentName.unflattenFromString(flat);    
        if (cmp != null) {
            hiddenPackages.add(cmp.getPackageName());

        }    
    }

    Intent intent = new Intent(Intent.ACTION_MAIN, null);    
    intent.addCategory(Intent.CATEGORY_LAUNCHER);   
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

    List<ResolveInfo> resolveInfoList = pm.queryIntentActivities(intent, 0);

    //Sort all apps    
    Collections.sort(resolveInfoList, new ResolveInfo.DisplayNameComparator(pm));

    for (ResolveInfo resolveInfo : resolveInfoList) {    
        ActivityInfo activityInfo = resolveInfo.activityInfo;
        int iconId = IconPackHelper.getInstance(context).getResourceIdForActivityIcon(activityInfo);
        if (!filteredPackages.contains(resolveInfo.activityInfo.packageName)) {    
            if (!hiddenPackages.contains(resolveInfo.activityInfo.packageName)) {    
                String appName = activityInfo.applicationInfo.loadLabel(pm).toString();     
                String packageName = activityInfo.packageName;    
                Drawable icon = null;  
                int extractedIconColor = 0;
                //toggle themed icon    
                if (iconPackHelper.isIconPackLoaded() && iconPackHelper.getThemedIcon(context, packageName)) {    
                    if (iconId != 0) {    
                        icon = IconPackHelper.getInstance(context).getIconPackResources().getDrawable(iconId); 
                        Bitmap iconBm = ImageUtils.drawableToBitmap(icon);    
                        extractedIconColor = ColorProvider.getDominantColor(iconBm);    
                    }    
                }
                if (icon == null || !IconPackHelper.getInstance(context).isIconPackLoaded()) {  
                    icon = activityInfo.applicationInfo.loadIcon(pm);
                    Bitmap iconBm = ImageUtils.drawableToBitmap(icon);
                    extractedIconColor = ColorProvider.getDominantColor(iconBm);
                }
                res.add(new ApplicationInfo(appName, icon, packageName, extractedIconColor));
            }
        }
    }

    return res;

}
Run Code Online (Sandbox Code Playgroud)

ND1*_*10_ 12

在Android 11中,我们可以看到很多改善隐私的更新。如果您的应用使用这些PackageManager方法来获取 user\xe2\x80\x99s 设备中已安装应用的列表,则您必须对使用 Android 11 的设备的代码进行一些更改。

\n

现在,对于使用 Android 11 的用户,代码保持不变,但\xe2\x80\x99 无法工作,除非你在AndroidManifest

\n
\n

有 3 种不同的方式查询已安装的应用程序

\n
\n

1.查询具体包

\n

如果您已经知道要查询哪些应用程序,只需<queries>AndroidManifest.

\n
<manifest package="com.nd1010.app">\n    <queries>\n        <package android:name="com.fake.app" /> //replace with com.android.wallpaper.livepicker\n        <package android:name="com.fake.game" /> //replace with com.gocalsd.symphlyx\n    </queries>\n    ...\n</manifest>\n
Run Code Online (Sandbox Code Playgroud)\n

2.使用intent过滤器进行查询

\n

如果您不知道\xe2\x80\x99 不知道要查询的应用程序的所有包名称,但有一组具有类似功能的应用程序要查询,那么您可以根据以下内容在元素内使用意图过滤<queries>器您的要求就像下面的代码片段中已经完成的那样。

\n
<manifest package="com.nd1010.app">\n    <queries>\n        <intent>\n            <action android:name="android.intent.action.SEND" />\n            <data android:mimeType="image/jpeg" />\n        </intent>\n    </queries>\n    ...\n</manifest>\n
Run Code Online (Sandbox Code Playgroud)\n

<intent>元素看起来很像,但几乎没有什么区别。<intent>元素有以下限制:

\n
    \n
  • 元素<intent>只能有一个<action>元素。
  • \n
  • <data>元素只能具有以下属性:mimeTypeschemehost
  • \n
\n

3.查询所有应用

\n

如果您想像之前一样查询用户的所有应用程序,则需要QUERY_ALL_PACKAGESAndroidManifest. 这是一个正常的权限,一旦安装应用程序就会被授予。

\n
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>\n
Run Code Online (Sandbox Code Playgroud)\n

理想情况下,应该请求最少量的包并尊重用户\xe2\x80\x99s 的隐私。在大多数情况下,不需要此权限\xe2\x80\x99,仅对于启动器之类的应用程序,询问用户查询手机上所有已安装应用程序的权限才有意义。

\n

我在探索该元素时注意到一个漏洞,<queries>如果您将其添加android.intent.action.MAIN为意图过滤器中的操作元素,则无需添加权限即可看到用户的几乎所有应用程序,因为几乎所有应用程序都会在AndroidManifest.

\n