Service中调用UsageStatsManager后台运行时数据不更新如何解决
问题原因与解决方案
为什么后台运行时UsageStatsManager无法正常工作
- 普通后台Service被系统回收:Android 8.0(API 26)开始对普通后台Service做了严格的运行限制,应用切到后台后,普通Service空闲数分钟就会被系统强制终止,你当前配置的是普通Service,没有前台服务标识,切后台后Service很快就会停止运行,自然不会继续更新使用时长数据。
- UsageStatsManager后台查询节流:系统为了降低功耗,对后台应用调用UsageStatsManager的频率和返回数据实时性做了限制,应用处于前台时可高频查询获取接近实时的统计数据,切到后台后系统会优先返回缓存的历史数据,不会实时更新最新的应用使用记录。
- 系统省电策略拦截:原生Android的省电优化以及国产ROM的后台管理策略,会默认限制后台应用调用敏感权限,
PACKAGE_USAGE_STATS属于受保护的特殊权限,很多系统会禁止后台应用调用该权限获取最新数据,只有应用回到前台时才会放开限制。
修复方案
- 将普通Service改为前台服务
前台服务是安卓允许的后台长期运行组件,需要在Service启动时调用startForeground()展示常驻通知,同时补充对应权限:
清单文件新增权限:
Service的<!-- 基础前台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Android 14及以上如果是数据同步场景补充该权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />onStartCommand方法中添加前台服务启动逻辑,设置一个常驻通知即可。 - 优化UsageStats查询逻辑
系统的应用使用统计数据本身有2-10秒的更新延迟,后台场景延迟更高,不要直接查询当前时间点的数据,调整查询的结束时间,同时降低查询频率,最少间隔1分钟查询一次:// 结束时间留10秒余量,避免拿到未更新的缓存数据 val endTime = System.currentTimeMillis() - 10 * 1000 val startTime = endTime - 1000 * 3600 * 24 var appList = usm.queryUsageStats( UsageStatsManager.INTERVAL_DAILY, startTime, endTime ) - 引导用户配置权限白名单
引导用户开启应用的「使用情况访问权限」,同时关闭系统对应用的省电优化,允许应用后台活动,避免被ROM的后台管理策略拦截。
内容的提问来源于stack exchange,提问作者Ammar Ahsan
相关产品推荐
相关产品推荐

