簡體   English   中英

使用 PackageManager 在 Android 11 上未填充應用程序列表

[英]List of apps doesn't populate on Android 11 using PackageManager

我正在使用 package 管理器在我的啟動器中獲取應用程序抽屜界面的應用程序列表。 一切正常,但在 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;

}

在 Android 11 中,我們可以看到很多改進隱私的更新。 如果您的應用程序使用PackageManager方法來獲取用戶設備中已安裝應用程序的列表,則您必須對使用 Android 11 的設備的代碼進行一些更改。

現在,對於使用 Android 11 的用戶,代碼保持不變,但除非您在AndroidManifest中添加一些其他元素,否則它將無法工作

有 3 種不同的方式來查詢已安裝的應用程序

1.查詢具體包

如果您已經知道要查詢哪些應用程序,只需在AndroidManifest<queries>元素中提及 package 名稱即可。

<manifest package="com.nd1010.app">
    <queries>
        <package android:name="com.fake.app" /> //replace with com.android.wallpaper.livepicker
        <package android:name="com.fake.game" /> //replace with com.gocalsd.symphlyx
    </queries>
    ...
</manifest>

2.使用intent filter查詢

如果您不知道要查詢的應用程序的所有 package 名稱,但有一組具有類似功能的應用程序要查詢,那么您可以根據您的要求在<queries>元素內使用意圖過濾器類似的要求已經在下面的代碼片段中完成。

<manifest package="com.nd1010.app">
    <queries>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="image/jpeg" />
        </intent>
    </queries>
    ...
</manifest>

<intent>元素看起來很像,但幾乎沒有區別。 <intent>元素有以下限制:

  • <intent>元素只能有一個<action>元素。
  • <data>元素只能具有以下屬性: mimeTypeschemehost

3.查詢所有應用

如果您想像之前一樣查詢用戶的所有應用程序,您需要在AndroidManifest中包含QUERY_ALL_PACKAGES權限。 這是一個正常的權限,一旦安裝應用程序就會被授予。

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

理想情況下,應該請求最少數量的包裹並尊重用戶的隱私。 在大多數情況下,不需要此權限,僅對於啟動器之類的應用程序,請求用戶允許查詢其手機上所有已安裝的應用程序才有意義。

我在探索<queries>元素時發現了一個漏洞,如果你在意圖過濾器中添加android.intent.action.MAIN作為動作元素,你可以在不添加權限的情況下看到用戶的幾乎所有應用程序,因為幾乎所有應用程序將在AndroidManifest中包含此元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM