1

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.

ClassA
  • 2,480
  • 1
  • 26
  • 57
  • `getInstalledPackages()` is fine on a background thread. I have corrected that 8-year-old answer of mine that you cited. Sorry for any confusion that I caused! – CommonsWare Mar 26 '18 at 15:50
  • @CommonsWare no worries, thank you for replying. – ClassA Mar 26 '18 at 16:03

0 Answers0