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

如何获取Android系统中各应用的屏幕使用时间及区分运行时长?

获取Android应用屏幕使用时间的实现方案

嘿,要获取Android系统中其他应用的屏幕使用时间(也就是用户实际交互的前台时长,区别于后台挂着的运行时长),核心是用Android官方提供的UsageStatsManager API,但得先搞定权限和版本适配问题,我给你理清楚具体步骤:

一、核心权限要求

首先你需要申请ACCESS_APP_USAGE_STATS权限,这是一个敏感系统权限,不能通过常规的requestPermissions()方法直接请求,必须引导用户手动到系统设置中开启权限。

权限检查与引导代码示例(Kotlin)

private fun hasUsageStatsPermission(): Boolean {
    val appOps = getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
    val mode = appOps.checkOpNoThrow(
        AppOpsManager.OPSTR_GET_USAGE_STATS,
        Process.myUid(),
        packageName
    )
    return mode == AppOpsManager.MODE_ALLOWED
}

private fun requestUsageStatsPermission() {
    // 跳转到应用使用权限设置页面
    startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
}

在你的Activity初始化时,先调用hasUsageStatsPermission()检查权限,没有的话就调用requestUsageStatsPermission()引导用户开启。

二、查询屏幕使用时间(前台时长)

从Android 5.0(API 21)开始,UsageStatsManager就提供了查询应用使用统计的能力,其中totalTimeInForeground字段就是我们要的屏幕使用时间(单位:毫秒),这个值代表应用处于前台活动状态、用户实际交互的时长,和后台运行时长完全区分开。

查询指定时间区间的应用前台时长代码示例(Kotlin)

private fun getAppForegroundUsage(startTime: Long, endTime: Long): List<Pair<String, Long>> {
    val usageStatsManager = getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
    // 查询指定时间区间内的使用统计数据,INTERVAL_DAILY可根据需求替换
    val usageStatsList = usageStatsManager.queryUsageStats(
        UsageStatsManager.INTERVAL_DAILY,
        startTime,
        endTime
    )

    return usageStatsList.mapNotNull { stats ->
        // 过滤掉没有前台使用记录的应用
        if (stats.totalTimeInForeground > 0) {
            // 获取应用名称(从包名转换)
            val appName = try {
                packageManager.getApplicationLabel(
                    packageManager.getApplicationInfo(stats.packageName, 0)
                ).toString()
            } catch (e: PackageManager.NameNotFoundException) {
                stats.packageName // 如果找不到应用信息,就用包名代替
            }
            // 返回应用名称和前台时长(毫秒)
            appName to stats.totalTimeInForeground
        } else null
    }.sortedByDescending { it.second } // 按前台时长从长到短排序
}

调用示例(获取今日的屏幕使用时间)

val calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, 0)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
val startTime = calendar.timeInMillis
val endTime = System.currentTimeMillis()

val appUsageList = getAppForegroundUsage(startTime, endTime)
// 遍历输出,把毫秒转成小时:时长 / 3600000
appUsageList.forEach { (appName, foregroundTime) ->
    val hours = foregroundTime / 3600000.0
    Log.d("AppUsage", "$appName 屏幕使用时间:%.2f小时".format(hours))
}

三、关键注意事项

  • 版本适配UsageStatsManager仅在Android 5.0及以上可用,低于该版本的系统无法通过官方API获取此数据。
  • 权限有效性:即使用户开启了权限,系统也可能会在应用长时间未使用后回收权限,所以每次查询前都要重新检查权限状态。
  • 运行时长vs屏幕使用时间:你提到的“运行时长”如果包含后台服务时间,UsageStatsManager并没有直接提供这个字段,若需要的话,可能需要结合ActivityManager的相关API,但Android 8.0及以上对后台进程的获取有严格限制,很难拿到准确的后台运行时长。而totalTimeInForeground是官方认可的、最准确的用户实际屏幕使用时间统计。

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

火山引擎 最新活动