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

Android开发:如何通过Usage Stats API计算应用使用时长?

嘿,我来帮你搞定Android应用里计算使用时长的问题!结合你的需求和已经做的工作,我给你两种可行的方案:

解决方案:计算应用使用时长的两种方式

1. 直接利用UsageStats API的原生字段(推荐)

其实你不用自己手动存储时间戳数组来计算时长——Android的UsageStats对象本身就包含了单次会话的开始、结束时间,以及总使用时长的字段,系统已经帮你处理好了应用前后台切换的会话划分,准确性更高。

核心思路

每个UsageStats实例对应一个应用的一段前台使用会话:

  • getFirstTimeStamp():会话开始的时间戳(应用进入前台的时间)
  • getLastTimeStamp():会话结束的时间戳(应用退到后台的时间)
  • 两者的差值就是这段会话的使用时长,你可以按应用分组,整理成你需要的格式。

示例代码(Kotlin)

// 获取UsageStatsManager实例
val usageStatsManager = getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
val endTime = System.currentTimeMillis()
val startTime = endTime - 24 * 60 * 60 * 1000 // 查询最近24小时的使用记录

// 查询使用统计数据
val usageStatsList = usageStatsManager.queryUsageStats(
    UsageStatsManager.INTERVAL_DAILY,
    startTime,
    endTime
)

// 按应用包名分组,整理成你需要的格式
val appUsageRecords = mutableMapOf<String, MutableList<Triple<String, Long, String>>>()
for (stats in usageStatsList) {
    val packageName = stats.packageName
    // 转换时间戳为HH:mm格式
    val sessionStartTimeStr = SimpleDateFormat("HH:mm", Locale.getDefault())
        .format(Date(stats.firstTimeStamp))
    // 计算会话时长(转成分钟)
    val sessionDurationMins = TimeUnit.MILLISECONDS.toMinutes(
        stats.lastTimeStamp - stats.firstTimeStamp
    )
    // 存入Map,按应用分组
    appUsageRecords.getOrPut(packageName) { mutableListOf() }
        .add(Triple(sessionStartTimeStr, sessionDurationMins, "mins"))
}

// 遍历输出,就和你给出的示例格式一致了
appUsageRecords.forEach { (appName, records) ->
    records.forEach { (time, duration, unit) ->
        println("$appName $time $duration $unit")
    }
}

2. 基于你已存储的时间戳数组计算

如果你已经手动存储了应用的时间戳数组,那需要先明确这些时间戳的含义:是应用每次进入前台的时间点,还是包含进入/退出的成对时间?

核心思路(假设存储的是「进入前台」的时间点)

  1. 把所有应用的时间戳按时间顺序排序(不管所属应用)
  2. 遍历排序后的列表:
    • 当前条目的结束时间 = 下一个条目的时间戳(如果存在)
    • 最后一个条目的结束时间 = 当前系统时间
    • 时长 = 结束时间 - 当前条目的时间戳
  3. 按应用整理结果即可。

示例代码(Kotlin)

// 假设你已存储的时间戳数组(示例数据,包名+时间戳)
val storedAppTimestamps = listOf(
    Pair("Facebook", 12*60*60*1000 + 59*60*1000), // 12:59
    Pair("Quora", 13*60*60*1000 + 30*60*1000),    // 1:30
    Pair("Facebook", 13*60*60*1000 + 45*60*1000)   // 1:45
)

// 按时间戳排序
val sortedTimestamps = storedAppTimestamps.sortedBy { it.second }
val usageResults = mutableListOf<String>()

for (i in sortedTimestamps.indices) {
    val (appName, startTime) = sortedTimestamps[i]
    // 确定结束时间
    val endTime = if (i < sortedTimestamps.size - 1) {
        sortedTimestamps[i+1].second
    } else {
        System.currentTimeMillis()
    }
    // 计算时长(转分钟)
    val durationMins = TimeUnit.MILLISECONDS.toMinutes(endTime - startTime)
    // 转换时间为HH:mm格式
    val timeStr = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(startTime))
    // 拼接成你需要的格式
    usageResults.add("$appName $timeStr $durationMins mins")
}

// 输出结果
usageResults.forEach { println(it) }
重要注意事项
  • 确保你的应用已经获取了android.permission.PACKAGE_USAGE_STATS权限:这个权限不能通过常规的requestPermissions()申请,需要引导用户到「设置 > 安全 > 有权查看使用情况的应用」中手动开启。
  • 时区问题:存储时间戳时建议用UTC时间,避免不同时区转换导致的时长计算错误。
  • 系统兼容性:部分系统应用或定制ROM可能不会正确上报使用状态,需要做兼容处理。

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

火山引擎 最新活动