项目中有需要统计应用的使用时长,每天0点获取前一天的应用使用时长。
使用了UsageStatsManager.queryUsageStats来获取,之前测试是正常的,但真正使用中却多次获取错误,当天未使用的应用也给统计出来了,而且时长和华为系统中的健康使用多出两倍或三倍
错误原因有人曾分析过
关于 UsageStatsManager.queryUsageStats 的注意事项及 UsageStatsService 的简单原理
文中提到,queryUsageStats 接口并不是按照传入的开始结束时间戳来计算的,而是受时区影响,所以如果使用2号的0点和24点时间戳传入,会获取到1号的数据,导致数据重复问题
需要改为使用queryEvents来计算,该方法返回Event数据包含开始结束时间内的所有使用过应用的activity的MOVE_TO_FOREGROUND、MOVE_TO_BACKGROUND 、USER_INTERACTION 等事件,可以拿来计算,但处理过程比较麻烦,可以直接反编译系统设置中统计相关逻辑
该页面为com.huawei.parentcontrol/com.huawei.parentcontrol.ui.activity.AppUsageDetailActivity
直接导出parentcontrol对应apk,使用jadx打开,查找AppUsageDetailActivity,对应AppUsageFragment
很容易找到关键的折线图相关,以此可以找到折线图的数据获取
把相关代码提取出来
object AppUsageStatHelper {
fun getAppUseTimeSevenDay(context: Context?, str: String): Map<String?, Long?>? {
val str2 = "AppUsageStatHelper"
if (context == null || TextUtils.isEmpty(str)) {
return HashMap(0)
}
val a: Long = m8244a(1)
val currentTimeMillis = System.currentTimeMillis()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
val usageStatsManager =
context.getSystemService(AppCompatActivity.USAGE_STATS_SERVICE) as UsageStatsManager
if (usageStatsManager != null) {
val queryEvents: UsageEvents =
usageStatsManager.queryEvents(a - 14400000, currentTimeMillis)
if (queryEvents == null) {
return HashMap(0)
}
val a2: Map<String?, Long?> = m6684a(
str,
queryEvents,
a,
currentTimeMillis,
"今天"
)
return a2
}
}
return null
}
fun m8244a(i: Int): Long {
if (i == 0) {
return TimeUtils.getWeeOfToday()
}
if (i != 1) {
return 0
}
val a: Long = TimeUtils.m8328a(6)
return a
}
/* renamed from: a */
private fun m6684a(
str: String,
usageEvents: UsageEvents?,
j: Long,
j2: Long,
str2: String
): Map<String?, Long?> {
val event = UsageEvents.Event()
val sevenDayUsageData = SevenDayUsageData(str, j, j2, str2)
if (usageEvents != null) {
while (usageEvents.getNextEvent(event)) {
if (str == event.getPackageName()) {
if (m6689a(event)) {
sevenDayUsageData.mo7089a(event)
}
}
}
}
sevenDayUsageData.mo11419c()
return sevenDayUsageData.mo11420d()
}
private fun m6689a(event: UsageEvents.Event?): Boolean {
return if (event == null) {
false
} else if (Build.VERSION.SDK_INT < 29 || event.getEventType() !== 23) {
val eventType: Int = event.getEventType()
if (eventType == 1 || eventType == 2) {
true
} else false
} else {
if ("com.huawei.himovie" == event.getPackageName()) {
false
} else true
}
}
internal class SevenDayUsageData(
str: String?, j: Long, j2: Long, /* renamed from: l */
private val f8542l: String
) :
BaseUsageData(str!!, j, j2) {
/* renamed from: j */
private val f8540j: MutableMap<String?, Long?> = HashMap()
/* renamed from: k */
private val f8541k = LongArray(7)
/* renamed from: a */
private fun m12496a(j: Long, j2: Long, i: Int) {
val obj: String
if (mo7091a(j, this.f4753c)) {
obj = f8542l
} else {
obj = TimeUtils.m8333a(java.lang.Long.valueOf(j))
}
var j3: Long = 86400000
if (f8540j.containsKey(obj)) {
val longValue = f8540j[obj]!!.toLong() + j2
if (longValue <= 86400000) {
j3 = longValue
}
f8540j[obj] = java.lang.Long.valueOf(j3)
} else if (j2 > 86400000) {
return
} else {
f8540j[obj] = java.lang.Long.valueOf(j2)
}
m12495a(m12497e(j), j2)
}
/* access modifiers changed from: protected */ /* renamed from: a */
override fun mo7088a(): String {
return "SevenDayUsageData"
}
/* access modifiers changed from: protected */ /* renamed from: c */
override fun mo7095c(j: Long) {
val j2 = this.f4754d
val j3 = this.f4755e
this.f4754d = j2 + (j - j3)
if (mo7091a(j3, j)) {
m12496a(j, j - this.f4755e, 1)
return
}
val f = m12498f(j)
val j4 = this.f4755e
m12496a(j4, f - j4, 2)
m12496a(j, j - f, 3)
}
/* renamed from: d */
fun mo11420d(): Map<String?, Long?> {
return f8540j
}
/* renamed from: e */
fun mo11421e(): LongArray {
return f8541k.clone()
}
/* renamed from: f */
fun mo11422f(): List<Long> {
val arrayList = ArrayList<Long>(7)
for (valueOf in f8541k) {
arrayList.add(java.lang.Long.valueOf(valueOf))
}
return arrayList
}
/* renamed from: e */
private fun m12497e(j: Long): Int {
return 6 - mo7087a(j)
}
/* renamed from: f */
private fun m12498f(j: Long): Long {
val instance = Calendar.getInstance()
instance.timeInMillis = j
instance[11] = 0
instance[12] = 0
instance[13] = 0
return instance.timeInMillis
}
/* renamed from: c */
fun mo11419c() {
if (this.f4756f == 1) {
val currentTimeMillis = System.currentTimeMillis()
mo7095c(currentTimeMillis)
this.f4755e = currentTimeMillis
}
}
/* renamed from: a */
private fun m12495a(i: Int, j: Long) {
val str = "SevenDayUsageData"
if (i >= 0) {
val jArr = f8541k
if (i < jArr.size) {
if (j < 0 || j > 86400000) {
return
} else {
jArr[i] = jArr[i] + j
return
}
}
}
}
}
abstract class BaseUsageData(/* renamed from: a */
protected var f4751a: String, /* renamed from: b */
protected var f4752b: Long, /* renamed from: c */
protected var f4753c: Long
) {
/* renamed from: d */
protected var f4754d: Long = 0
/* renamed from: e */
protected var f4755e: Long = 0
/* renamed from: f */
protected var f4756f = 0
/* renamed from: g */
protected var f4757g: MutableMap<String, Int> = HashMap()
/* renamed from: h */
private val f4758h = Calendar.getInstance()
/* renamed from: i */
private val f4759i = Calendar.getInstance()
/* renamed from: e */
private fun m6472e(j: Long) {
val j2 = this.f4755e
if (j > j2) {
this.f4755e = j
} else if (j < j2) {
val a = mo7088a()
} else {
val a2 = mo7088a()
}
}
/* renamed from: f */
private fun m6473f(j: Long) {
val j2 = this.f4752b
if (j >= j2) {
if (this.f4755e < j2) {
this.f4755e = j2
}
mo7095c(j)
this.f4755e = j
}
}
/* renamed from: a */
abstract fun mo7088a(): String
/* renamed from: a */
fun mo7089a(event: UsageEvents.Event) {
if (mo7094b(event)) {
val timeStamp: Long = event.getTimeStamp()
val className: String = event.getClassName()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
if (this.f4757g.getOrDefault(className, Integer.valueOf(0)).toInt() == 1) {
if (timeStamp > this.f4755e) {
m6473f(timeStamp)
} else {
}
}
}
val eventType: Int = event.getEventType()
if (eventType == 1) {
m6472e(timeStamp)
this.f4757g[className] = Integer.valueOf(eventType)
} else if (eventType == 2) {
this.f4757g[className] = Integer.valueOf(eventType)
} else if (eventType != 23) {
} else {
this.f4757g.remove(className)
}
this.f4756f = event.getEventType()
}
}
/* access modifiers changed from: protected */ /* renamed from: a */
fun mo7090a(i: Int): Boolean {
return i == 1 || i == 2 || i == 23
}
/* renamed from: b */
fun mo7093b(): Long {
return this.f4754d
}
/* renamed from: c */
abstract fun mo7095c(j: Long)
/* access modifiers changed from: protected|final */ /* renamed from: d */
fun mo7096d(j: Long): Long {
this.f4758h.timeInMillis = j
this.f4758h[11] = 0
this.f4758h[12] = 0
this.f4758h[13] = 0
this.f4758h[14] = 0
return this.f4758h.timeInMillis
}
/* access modifiers changed from: protected */ /* renamed from: b */
fun mo7094b(event: UsageEvents.Event?): Boolean {
if (event == null) {
return false
}
val str = f4751a
if (str == null || str != event.getPackageName()) {
return false
}
val eventType: Int = event.getEventType()
if (mo7090a(eventType)) {
return true
}
return false
}
/* access modifiers changed from: protected|final */ /* renamed from: b */
fun mo7092b(j: Long): Int {
this.f4758h.timeInMillis = j
return this.f4758h[11]
}
/* access modifiers changed from: protected|final */ /* renamed from: a */
fun mo7091a(j: Long, j2: Long): Boolean {
this.f4758h.timeInMillis = j
f4759i.timeInMillis = j2
return this.f4758h[6] === f4759i[6]
}
/* access modifiers changed from: protected|final */ /* renamed from: a */
fun mo7087a(j: Long): Int {
this.f4758h.timeInMillis = j
f4759i.timeInMillis = this.f4753c
return f4759i[6] - this.f4758h[6]
}
init {
if (TextUtils.isEmpty(f4751a)) {
}
}
}
}
调用
val appUsageStatsByTime = AppUsageStatHelper.getAppUseTimeSevenDay(
mContext,
"com.jingdong.app.mall"
)
结果为{“今天”:251654,”8/17”:571679}
转化为分钟,今天4分钟,昨天9分钟,与系统统计信息一致