How do I check if an app is a non-system app in Android?
PackageManager pm = mcontext.getPackageManager();List<PackageInfo> list = pm.getInstalledPackages(0);for(PackageInfo pi : list) { ApplicationInfo ai = pm.getApplicationInfo(pi.packageName, 0); System.out.println(">>>>>>packages is<<<<<<<<" + ai.publicSourceDir); if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { System.out.println(">>>>>>packages is system package"+pi.packageName); }}
I was under the impression that all apps in the system image are system apps (and normally installed in /system/app
).
If FLAG_SYSTEM
is only set to system applications, this will work even for apps in external storage:
boolean isUserApp(ApplicationInfo ai) { int mask = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; return (ai.flags & mask) == 0;}
An alternative is to use the pm
command-line program in your phone.
Syntax:
pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]pm list packages: prints all packages, optionally only those whose package name contains the text in FILTER. Options: -f: see their associated file. -d: filter to only show disbled packages. -e: filter to only show enabled packages. -s: filter to only show system packages. -3: filter to only show third party packages. -i: see the installer for the packages. -u: also include uninstalled packages.
Code:
ProcessBuilder builder = new ProcessBuilder("pm", "list", "packages", "-s");Process process = builder.start();InputStream in = process.getInputStream();Scanner scanner = new Scanner(in);Pattern pattern = Pattern.compile("^package:.+");int skip = "package:".length();Set<String> systemApps = new HashSet<String>();while (scanner.hasNext(pattern)) { String pckg = scanner.next().substring(skip); systemApps.add(pckg);}scanner.close();process.destroy();
Then:
boolean isUserApp(String pckg) { return !mSystemApps.contains(pckg);}
You can check the signature of application which it signed with system. Like below
/** * Match signature of application to identify that if it is signed by system * or not. * * @param packageName * package of application. Can not be blank. * @return <code>true</code> if application is signed by system certificate, * otherwise <code>false</code> */public boolean isSystemApp(String packageName) { try { // Get packageinfo for target application PackageInfo targetPkgInfo = mPackageManager.getPackageInfo( packageName, PackageManager.GET_SIGNATURES); // Get packageinfo for system package PackageInfo sys = mPackageManager.getPackageInfo( "android", PackageManager.GET_SIGNATURES); // Match both packageinfo for there signatures return (targetPkgInfo != null && targetPkgInfo.signatures != null && sys.signatures[0] .equals(targetPkgInfo.signatures[0])); } catch (PackageManager.NameNotFoundException e) { return false; }}
You can get more code on my blog How to check if application is system app or not (By signed signature)