Android UsageStatsManager:获取手机当前运行应用列表的技术问题
获取当前运行应用列表的问题排查与修正方案
嘿,我看你正在尝试用UsageStatsManager获取手机上当前运行的应用列表,先帮你分析下现有代码里的潜在问题,再给出调整后的可行方案:
现有代码的问题点
- 时间范围计算不合理:
time - 10000*10000算出来是当前时间减去约2.77小时,这个区间可能不符合你获取"当前运行应用"的需求;另外如果时间范围设置不当(比如开始时间晚于结束时间),queryUsageStats会直接返回空列表。 - 缺失关键权限:使用
UsageStatsManager必须声明PACKAGE_USAGE_STATS权限,而且这个权限没法通过常规的动态权限申请流程获取,必须引导用户到系统设置里手动开启。 - 调试逻辑有局限:你只在
appList不为空但长度为0时打印日志,没法覆盖appList本身为null的情况,不利于排查问题。
修正后的完整实现
1. 先在Manifest中声明权限
在AndroidManifest.xml里添加权限声明:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
2. 检查并引导开启权限
调用UsageStatsManager前,先确认权限是否已开启,没开启的话跳转到设置页面:
private boolean hasUsageStatsPermission() { AppOpsManager appOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE); int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), getPackageName()); return mode == AppOpsManager.MODE_ALLOWED; } // 在需要获取应用列表的地方调用权限检查 if (!hasUsageStatsPermission()) { Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS); startActivity(intent); return; }
3. 修正后的应用列表获取代码
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { UsageStatsManager usm = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE); long currentTime = System.currentTimeMillis(); // 获取最近10分钟的应用使用情况,可根据需求调整时间范围 long startTime = currentTime - 10 * 60 * 1000; List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime, currentTime); if (appList == null) { Log.d("AppListLog", "获取应用列表失败,appList为null"); } else if (appList.size() == 0) { Log.d("AppListLog", "应用列表为空,请检查权限是否开启或时间范围是否合理"); } else { // 遍历处理获取到的应用数据 for (UsageStats usageStats : appList) { Log.d("AppInfo", "包名:" + usageStats.getPackageName() + " 最后活跃时间:" + usageStats.getLastTimeUsed()); } } }
额外说明
UsageStatsManager.INTERVAL_DAILY是统计区间类型,你可以根据需求换成INTERVAL_HOURLY、INTERVAL_WEEKLY等,但要确保时间范围和区间类型匹配。- 如果想精准获取当前前台运行的应用,
UsageStatsManager的方式不算最优解,在Android 10及以上可以结合AppOpsManager的OPSTR_ACTIVITY_RECORD权限和ActivityManager,或者使用AccessibilityService(但需要用户开启辅助功能)。
内容的提问来源于stack exchange,提问作者anon_945500




