我知道我们可以通过使用类似的内容(过去询问过here)来获取指定应用的网络使用情况(到目前为止,从某个特定时间开始,移动和Wifi占用的总带宽):>
private final static int[] NETWORKS_TYPES = new int[]{ConnectivityManager.TYPE_WIFI, ConnectivityManager.TYPE_MOBILE};
long rxBytes=0L, txBytes=0L;
final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final String subscriberId = telephonyManager.getSubscriberId();
final ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(packageName, 0);
final int uid = applicationInfo.uid;
for (int networkType : NETWORKS_TYPES) {
final NetworkStats networkStats = networkStatsManager.queryDetailsForUid(networkType, subscriberId, 0, System.currentTimeMillis(), uid);
final Bucket bucketOut = new Bucket();
while (true) {
networkStats.getNextBucket(bucketOut);
final long rxBytes = bucketOut.getRxBytes();
if (rxBytes >= 0)
totalRx += rxBytes;
final long txBytes = bucketOut.getTxBytes();
if (txBytes >= 0)
totalTx += txBytes;
if (!networkStats.hasNextBucket())
break;
}
}
}
文档:
也可以获取全球网络使用情况(使用TrafficStats.getUidRxBytes(applicationInfo.uid)
和TrafficStats.getUidTxBytes(applicationInfo.uid)
),但这不是该线程的全部用途。
Android Q似乎计划导致许多设备标识功能停止工作,getSubscriberId
是其中之一。
我试图将targetSdk设置为29(Q),看看当我尝试使用它时会发生什么。
不出所料,我遇到了一个异常,向我表明我不能再这样做了。它说:
019-06-11 02:08:01.871 13558-13558/com.android.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.myapplication, PID: 13558
java.lang.SecurityException: getSubscriberId: The user 10872 does not meet the requirements to access device identifiers.
at android.os.Parcel.createException(Parcel.java:2069)
at android.os.Parcel.readException(Parcel.java:2037)
at android.os.Parcel.readException(Parcel.java:1986)
at com.android.internal.telephony.IPhoneSubInfo$Stub$Proxy.getSubscriberIdForSubscriber(IPhoneSubInfo.java:984)
at android.telephony.TelephonyManager.getSubscriberId(TelephonyManager.java:3498)
at android.telephony.TelephonyManager.getSubscriberId(TelephonyManager.java:3473)
在Internet和此处搜索时,我看不到提到的内容,但是我发现了类似的问题,即获取IMEI和其他标识符:
因此,到目前为止,我只是在此处提交了一个错误报告(包括示例项目):
https://issuetracker.google.com/issues/134919382
是否可以在Android Q上获得指定应用程序的网络使用率(定向到该应用程序时)?也许没有SubscriberId?
如果是,怎么办?
如果没有,是否可以通过拥有root或通过adb来实现?
编辑:
好的,我不知道如何正式使用它,但是至少对于root用户访问来说,可以使用从this solution找到的here获取用户ID。
类似的意思:
@SuppressLint("MissingPermission", "HardwareIds")
fun getSubscriberId(telephonyManager: TelephonyManager): String? {
try {
return telephonyManager.subscriberId
} catch (e: Exception) {
}
val commandResult = Root.runCommands("service call iphonesubinfo 1 | grep -o \"[0-9a-f]\\{8\\} \" | tail -n+3 | while read a; do echo -n \"\\u\${a:4:4}\\u\${a:0:4}\"; done")
val subscriberId = commandResult?.getOrNull(0)
return if (subscriberId.isNullOrBlank()) null else subscriberId
}
这当然不是官方的解决方案,但是总比没有好...
答案 0 :(得分:0)
您提到的主题的comment中的Google团队说:
“ 状态:无法解决(预期行为)
这是按预期工作。 IMEI是个人标识符,根据政策,不会授予应用程序。没有解决方法。“。所以我猜想NetworkStatsManager
类中需要IMSI(也被认为是个人标识符)才能工作的方法(例如queryDetailsForUid(int, String, long, long, int)
)您可以使用这些方法来获取应用程序的Wifi使用情况详细信息(通过为用户ID传递空字符串),但是要获取移动设备使用情况详细信息,您现在必须依靠旧的TrafficStats
类,直到问题得到注意并得到解决。
答案 1 :(得分:0)
我们正在使用NetworkStatsManager.querySummaryForDevice()。由于一个偶然的错误,我们在Q中将null作为MOBILE的subscriberId传递了。它似乎正在我们的设备上运行。我不确定这是错误还是功能,但是这些值是否符合我们预期的蜂窝电话使用率。
话虽如此,我们只能在这个用例中使用TrafficStats,但是在Pie之前是不稳定的。