gpt4 book ai didi

android - 如何在 Android Q 上获取应用程序的网络使用情况?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:20:33 24 4
gpt4 key购买 nike

背景

我知道我们可以通过使用类似的东西(过去问过,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;
}
}
}

文档:

https://developer.android.com/reference/android/app/usage/NetworkStatsManager.html#queryDetailsForUid(int,%20java.lang.String,%20long,%20long,%20int)

也可以获取全局网络使用情况(使用 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)

在互联网和此处搜索时,我没有看到提到这一点,但我发现了类似的问题,即获取 IMEI 和其他标识符:

所以现在我只是在这里做了一个关于它的错误报告(包括一个示例项目):

https://issuetracker.google.com/issues/134919382

问题

是否可以获取 Android Q 上指定应用的网络使用情况(针对它时)?也许没有 subscriberId?

如果是,怎么做到的?

如果不行,是否可以通过 root 或通过 adb 实现?


编辑:

好的,我不知道如何正式使用它,但至少对于 root 访问,可以使用 this solution 获取 subscriberId , 从 here 中找到.

意思是这样的:

@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
}

当然,这不是官方解决方案,但总比没有好...

编辑:通过 root 获取它的部分是错误的。它没有任何帮助。

最佳答案

您可以为 API 29 及更高版本提供空值。它返回 WIFI 和移动数据的值。

Documentation:

If applicable, the subscriber id of the network interface.Starting with API level 29, the subscriberId is guarded by additional restrictions. Calling apps that do not meet the new requirements to access the subscriberId can provide a null value when querying for the mobile network type to receive usage for all mobile networks. For additional details see TelephonyManager.getSubscriberId().

权限(不要忘记获得用户的许可):

<uses-permission android:name="android.permission.READ_PHONE_STATE"
android:maxSdkVersion="28"/>
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />

示例代码:

//network stats
NetworkStatsManager networkStatsManager = (NetworkStatsManager) activity.getSystemService(Context.NETWORK_STATS_SERVICE);
int[] networkTypes = new int[]{NetworkCapabilities.TRANSPORT_CELLULAR, NetworkCapabilities.TRANSPORT_WIFI};
String subscriberId;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
TelephonyManager telephonyManager = (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE);
try {
subscriberId = telephonyManager.getSubscriberId(); //MissingPermission
} catch (SecurityException e) {
subscriberId = null;
}

} else {
subscriberId = null;
}

获取应用的 NetworkStats:

long receivedBytes = 0;
long transmittedBytes = 0;

for (int networkType : networkTypes) {
NetworkStats networkStats;
try {
networkStats = networkStatsManager
.queryDetailsForUid(networkType,
subscriberId,
0,
System.currentTimeMillis(),
appUid);
} catch (SecurityException e) {
networkStats = null;
}

if(networkStats != null) {
NetworkStats.Bucket bucketOut = new NetworkStats.Bucket();
while (networkStats.hasNextBucket()) {
networkStats.getNextBucket(bucketOut);
long rxBytes = bucketOut.getRxBytes();
long txBytes = bucketOut.getTxBytes();
if (rxBytes >= 0) {
receivedBytes += rxBytes;
}
if (txBytes >= 0) {
transmittedBytes += txBytes;
}
}
networkStats.close();
}
}

关于android - 如何在 Android Q 上获取应用程序的网络使用情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56611173/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com