Android中telephonyManager.subscriberId返回null,求适配Q+的替代方案
替代方案:无需subscriberId获取移动数据用量
Android Q(API 29)及以上版本出于隐私保护,普通应用已经无法获取subscriberId(比如IMSI),所以你当前的代码必然返回null。要获取两个日期之间的移动数据用量,完全不需要依赖这个字段,直接用NetworkStatsManager即可实现。
实现步骤
1. 申请必要权限
需要添加PACKAGE_USAGE_STATS权限到Manifest:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
注意:这个权限属于特殊权限,无法通过常规的requestPermissions方法申请,必须引导用户跳转到系统设置页面开启:
fun requestUsageStatsPermission(context: Context) { val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS) context.startActivity(intent) }
2. 使用NetworkStatsManager查询数据用量
以下是查询指定时间段内整体移动数据用量的代码示例:
fun getMobileDataUsage(startTime: Long, endTime: Long, context: Context): Long { val networkStatsManager = context.getSystemService(Context.NETWORK_STATS_SERVICE) as NetworkStatsManager var totalBytes = 0L try { // 查询移动网络(TYPE_MOBILE)的总数据用量 val bucket = networkStatsManager.querySummary( ConnectivityManager.TYPE_MOBILE, null, // 不需要subscriberId,传null即可 startTime, endTime ) while (bucket.hasNextBucket()) { bucket.nextBucket() totalBytes += bucket.rxBytes + bucket.txBytes } } catch (e: SecurityException) { // 权限未开启时抛出异常,需处理 e.printStackTrace() } return totalBytes }
如果需要查询单个应用的移动数据用量,可以修改为:
fun getAppMobileDataUsage(uid: Int, startTime: Long, endTime: Long, context: Context): Long { val networkStatsManager = context.getSystemService(Context.NETWORK_STATS_SERVICE) as NetworkStatsManager var totalBytes = 0L try { val stats = networkStatsManager.queryDetailsForUid( ConnectivityManager.TYPE_MOBILE, null, startTime, endTime, uid ) while (stats.hasNextBucket()) { stats.nextBucket() totalBytes += stats.rxBytes + stats.txBytes } } catch (e: SecurityException) { e.printStackTrace() } return totalBytes }
关键说明
NetworkStatsManager不需要依赖subscriberId,完全可以独立完成数据用量统计- 若你的应用针对Android 10+,必须适配隐私权限规则,放弃对
subscriberId的依赖 - 测试时务必确保已经在系统设置中开启了应用的"使用情况访问权限"
内容的提问来源于stack exchange,提问作者Riyaz Shaik
相关产品推荐
相关产品推荐

