According to this questions/answers:
getInstalledPackages
should be run on the main thread.
But, my UI is being blocked until all the "packages" are loaded.
@CommonsWare mentioned the following:
Also, if you are using calls on PackageManager that return multiple results (e.g., getInstalledPackages(), try asking for no flags on that call, then retrieving the values for each package individually, to avoid getting a lot of data on a lot of entries at once.
This sounds like a possible solution to my problem, but I can't find any info about this.
I tried experimenting with different flags after seeing this answer and this is how I currently get/set the app name, package name and app icon:
public class AppManager {
private Context mContext;
private ArrayList<AppInfo> myApps;
public AppManager(Context c) {
mContext = c;
myApps = new ArrayList<>();
}
public ArrayList<AppInfo> getApps() {
loadApps();
return myApps;
}
private void loadApps() {
int flags = PackageManager.GET_META_DATA | PackageManager.GET_SHARED_LIBRARY_FILES | PackageManager.GET_UNINSTALLED_PACKAGES;
PackageManager pm = mContext.getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(flags);
for (ApplicationInfo appInfo : packages) {
if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 1) {
// Installed by user
AppInfo newApp = new AppInfo();
newApp.setAppName(getApplicationLabelByPackageName(appInfo.packageName));
newApp.setAppPackage(appInfo.packageName);
newApp.setAppIcon(getAppIconByPackageName(appInfo.packageName));
myApps.add(newApp);
}
Collections.sort(myApps, new Comparator<AppInfo>() {
@Override
public int compare(AppInfo s1, AppInfo s2) {
return s1.getAppName().compareToIgnoreCase(s2.getAppName());
}});
}
}
// Custom method to get application icon by package name
private Drawable getAppIconByPackageName(String packageName) {
Drawable icon;
try {
icon = mContext.getPackageManager().getApplicationIcon(packageName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
// Get a default icon
icon = ContextCompat.getDrawable(mContext, R.drawable.ic_launcher_background);
}
return icon;
}
// Custom method to get application label by package name
private String getApplicationLabelByPackageName(String packageName) {
PackageManager packageManager = mContext.getPackageManager();
ApplicationInfo applicationInfo;
String label = "Unknown";
try {
applicationInfo = packageManager.getApplicationInfo(packageName, 0);
if (applicationInfo != null) {
label = (String) packageManager.getApplicationLabel(applicationInfo);
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return label;
}
}
Even though the UI is not blocked for very long, it is still noticeable.