You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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_HOURLYINTERVAL_WEEKLY等,但要确保时间范围和区间类型匹配。
  • 如果想精准获取当前前台运行的应用UsageStatsManager的方式不算最优解,在Android 10及以上可以结合AppOpsManagerOPSTR_ACTIVITY_RECORD权限和ActivityManager,或者使用AccessibilityService(但需要用户开启辅助功能)。

内容的提问来源于stack exchange,提问作者anon_945500

火山引擎 最新活动