You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中精准获取Android设备其他应用的使用时长?

精准统计Android应用使用时长的可行方案

针对你遇到的UsageStatsManager返回数据误差大、部分应用失效的问题,结合你提到的AppBlocker在旧设备上的精准表现,以下是无需依赖高API级别AppUsageStatistics的解决思路:

一、优化UsageStatsManager的查询逻辑

不要局限于最简调用,通过调整查询参数和数据处理逻辑提升精度:

  • 细化时间切片:避免一次性查询大时间范围的统计数据,改用INTERVAL_HOURLY或INTERVAL_DAILY拆分查询后合并结果,减少系统统计的聚合误差。
  • 区分统计类型:遍历UsageStats时,重点提取getTotalTimeForeground()(前台活跃时长),而非总运行时长,过滤后台进程的无效统计。
  • 匹配进程与包名:部分应用存在多进程情况,需结合ActivityManager.getRunningAppProcesses()获取进程对应的包名,补全UsageStats中缺失的统计项。
  • 强制权限校验:确保已获取PACKAGE_USAGE_STATS权限,代码中需引导用户跳转到系统设置开启:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);

二、基于AccessibilityService的自主追踪

这是旧设备上实现精准统计的核心方案(推测AppBlocker即采用此方式):

  • 注册AccessibilityService,监听TYPE_WINDOW_STATE_CHANGED事件,实时捕获当前前台窗口的包名。
  • 维护本地时间戳记录:当窗口切换到目标应用时记录进入时间,切换离开时计算时长并存储到本地数据库,完全自主统计,不受系统API误差影响。
  • 关键代码示例(服务内事件处理):
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
        String packageName = event.getPackageName().toString();
        long currentTime = System.currentTimeMillis();
        // 从本地读取上一个活跃应用的进入时间
        if (lastPackage != null && !lastPackage.equals(packageName)) {
            long duration = currentTime - lastEnterTime;
            // 将lastPackage的时长存入本地存储
            saveAppUsage(lastPackage, duration);
        }
        lastPackage = packageName;
        lastEnterTime = currentTime;
    }
}
  • 注意:需在Manifest中声明服务并配置权限,引导用户在系统设置中开启辅助功能授权。

三、特殊应用的兼容处理

针对部分应用(如后台持续运行的服务、多进程应用)的统计失效问题:

  • 结合ActivityManager.getRunningTasks()(API 21后需特殊权限,低版本可用)辅助验证前台应用状态。
  • 对于系统应用,可通过读取UsageStats中的getLastTimeUsed()结合时间差,补全缺失的时长数据。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 17:53:21