前言
目前正是Android 11 馬上要發(fā)布的時(shí)期,當(dāng)前在Android手機(jī)上獲取應(yīng)用安裝列表,要從三個(gè)維度上區(qū)分:獲取方法、系統(tǒng)版本、是否系統(tǒng)應(yīng)用。
- 獲取方法:至少有兩種方法,它們的行為結(jié)果會(huì)有所差異
- 系統(tǒng)版本:從 Android 11 開始,應(yīng)用列表的獲取將受到限制
- 是否系統(tǒng)應(yīng)用:系統(tǒng)應(yīng)用與非系統(tǒng)應(yīng)用的獲取結(jié)果,也不盡相同
獲取方法介紹
獲取所有應(yīng)用列表(系統(tǒng)應(yīng)用+非系統(tǒng)應(yīng)用),常用的方法有2種:Shell命令行、系統(tǒng)API。
而要進(jìn)一步區(qū)分是否系統(tǒng)應(yīng)用,只要對(duì)上述結(jié)果進(jìn)行一次過濾即可。下面分別介紹:
1.shell命令行
pm list packages
示例代碼:
private List<String> getPkgList() {
List<String> packages = new ArrayList<String>();
try {
Process p = Runtime.getRuntime().exec("pm list packages");
InputStreamReader isr = new InputStreamReader(p.getInputStream(), "utf-8");
BufferedReader br = new BufferedReader(isr);
String line = br.readLine();
while (line != null) {
line = line.trim();
if (line.length() > 8) {
String prefix = line.substring(0, 8);
if (prefix.equalsIgnoreCase("package:")) {
line = line.substring(8).trim();
if (!TextUtils.isEmpty(line)) {
packages.add(line);
}
}
}
line = br.readLine();
}
br.close();
p.destroy();
} catch (Throwable t) {
t.printStacktraces();
}
return packages;
}
2.系統(tǒng)API
PackageManager.getInstalledPackages()
示例代碼:
private List<String> getPkgListNew() {
List<String> packages = new ArrayList<String>();
try {
List<PackageInfo> packageInfos = context.getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES |
PackageManager.GET_SERVICES);
for (PackageInfo info : packageInfos) {
String pkg = info.packageName;
packages.add(pkg);
}
} catch (Throwable t) {
t.printStackTrace();;
}
return packages;
}
判斷是否系統(tǒng)應(yīng)用
// 通過packName得到PackageInfo,作為參數(shù)傳入即可
private boolean isSystemApp(PackageInfo pi) {
boolean isSysApp = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1;
boolean isSysUpd = (pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 1;
return isSysApp || isSysUpd;
}
總結(jié)對(duì)比
- 測(cè)試機(jī):Google Pixel 3 XL
- 系統(tǒng)應(yīng)用:262個(gè)
- 非系統(tǒng)應(yīng)用:2個(gè)(包括測(cè)試demo)

說明:
- 這里說的權(quán)限是:QUERY_ALL_PACKAGES,Android 11 新增權(quán)限,不用動(dòng)態(tài)申請(qǐng)
- 這里說的
>= Android 11是:targetSdkVersion 為 Android 11 且 運(yùn)行在11的設(shè)備上
補(bǔ)充:廣播監(jiān)聽?wèi)?yīng)用安裝/卸載的行為變化
如果使用了廣播,監(jiān)聽?wèi)?yīng)用安裝與卸載動(dòng)作,那么在 Android 11 上也有一些行為變化。
概括來(lái)講,就是 Android 11 下,若無(wú) QUERY_ALL_PACKAGES 權(quán)限,則無(wú)法監(jiān)聽到 安裝 動(dòng)作。
Android 11 之前
- 能監(jiān)聽到 安裝/卸載
Android 11 開始
- 若無(wú) QUERY_ALL_PACKAGES 權(quán)限:只能監(jiān)聽到 卸載
- 若有 QUERY_ALL_PACKAGES 權(quán)限:仍能監(jiān)聽到 安裝/卸載