核心 API
PackageManager.getInstalledApplications(flags):獲取所有應用 ApplicationInfo
PackageManager.getLaunchIntentForPackage(packageName):判斷是否有啟動入口(用戶可見)
ApplicationInfo.flags:區分系統應用(FLAG_SYSTEM)、更新的系統應用(FLAG_UPDATED_SYSTEM_APP)、用戶應用
實體類設計
public class AppInfo {
private Drawable appIcon;
private String appName;
private String appVersion;
private String packageName;
private boolean isUserApp;
// 構造方法、Getter/Setter、toString()...
}
掃描並過濾用戶應用
public List getUserApps(Context context) {
PackageManager pm = context.getPackageManager();
List apps = pm.getInstalledApplications(PackageManager.GET_META_DATA);
List result = new ArrayList<>();
for (ApplicationInfo info : apps) {
// 僅保留有啟動圖標的應用
if (pm.getLaunchIntentForPackage(info.packageName) == null) continue;
// 過濾系統應用
if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 1) continue;
if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 1) continue;
// 獲取詳細信息
AppInfo appInfo = new AppInfo();
appInfo.setPackageName(info.packageName);
appInfo.setAppName(pm.getApplicationLabel(info).toString());
appInfo.setAppIcon(pm.getApplicationIcon(info));
try {
PackageInfo pkgInfo = pm.getPackageInfo(info.packageName, 0);
appInfo.setAppVersion(pkgInfo.versionName);
} catch (PackageManager.NameNotFoundException e) {
appInfo.setAppVersion("未知");
}
appInfo.setUserApp(true);
result.add(appInfo);
}
return result;
}
獲取所有應用(含系統)字符串列表
public String getInstalledAppListAsString(Context context) {
PackageManager pm = context.getPackageManager();
List apps = pm.getInstalledApplications(PackageManager.GET_GIDS);
StringBuilder sb = new StringBuilder();
for (ApplicationInfo app : apps) {
if (pm.getLaunchIntentForPackage(app.packageName) != null) {
if ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 1 &&
(app.flags & ApplicationInfo.FLAG_SYSTEM) != 1) {
sb.append(app.packageName).append(';');
}
}
}
return sb.toString();
}
權限聲明
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> // Android 11+
<queries>
<intent>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent>
</queries>
性能優化建議
- 使用
PackageManager.GET_META_DATA 而非 GET_GIDS 減少開銷
- 異步線程執行掃描,避免 ANR
- 結果緩存,避免重複查詢
- Android 11+ 需在 Manifest 中聲明
<queries> 否則列表為空