I am using package manager to get a list of apps for an app drawer interface in my launcher. Everything works as it should but on Android 11,the only app that shows is the Android Settings app. What changed to make this not work anymore and/or what should i do to make it work? Are app list now based on user profiles?
Here is my current list code
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;
}
In Android 11, we can see a lot of updates that improve privacy. If your app uses the PackageManager
methods to get the list of installed apps in the user's device, you will have to make some changes in your code for devices using Android 11.
Now for your users using Android 11, the code remains the same but it won't work unless you add some additional elements in the AndroidManifest
There are 3 different ways of querying installed apps
1.Query specific packages
If you already know which apps you want to query just mention the package names inside the <queries>
element in the AndroidManifest
.
<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.Query using intent filter
In case you don't know all the package names of the apps that you want to query but there is a set of apps with similar functionality that you want to query then you can use an intent filter inside the <queries>
element according to your requirements like it has been done in the code snippet below.
<manifest package="com.nd1010.app">
<queries>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="image/jpeg" />
</intent>
</queries>
...
</manifest>
The <intent>
element looks like but there are few differences. <intent>
element has the following restrictions:
<intent>
element can have only one <action>
element. <data>
element can only have the following attributes: mimeType
, scheme
and host
. 3.Query all the apps
If you want to query all the apps of the user like you were doing earlier, you need to include QUERY_ALL_PACKAGES
permission in the AndroidManifest
. It is a normal permission and it is granted as soon as the app is installed.
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
Ideally one should request the least amount of packages and respect the user's privacy. In most cases this permission won't be required, only for apps like launchers it makes sense to ask the user for permission to query all the installed apps on their phone.
There is one loophole that I noticed while exploring the <queries>
element if you add android.intent.action.MAIN
as the action element in the intent filter, you can see almost all the apps of the user without adding the permission since almost all apps would have this element in the AndroidManifest
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.