即使在Android N上,如何获得应用程序(或总体)的当前网络使用情况?

and*_*per 16 networking android

正如标题所说.我想知道特定应用在特定时间每秒使用的字节数.

也许我可以使用" netstat "命令?但如果是这样,我如何将其过滤到特定的应用/流程?

我还需要获得一些许可吗?

目前人们说使用TrafficStats.getUidRxBytes(packageInfo.uid),但是,从这里:https://developer.android.com/reference/android/net/TrafficStats.html#getUidRxBytes (int ),它表示不支持N,我应该使用NetworkStatsManager.有没有任何使用它的例子?

也许合并的解决方案?

编辑:我试图在Android N上使用NetworkStatsManager,但我失败了.我找不到任何关于如何使用它的示例,并且关于它的所有stackOverflow问题都是类似的,因为它无法很好地使用它.如果有人知道如何使用它,请写下来.

R. *_*ski 21

使用NetworkStats并不复杂.

设备API级别必须至少为23.以下是开始使用之前所需的一些步骤 NetworkStatsManager

  1. 在以下位置声明所需的权限AndroidManifest.xml:

    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission
        android:name="android.permission.PACKAGE_USAGE_STATS"
        tools:ignore="ProtectedPermissions"/>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 请求许可 Activity

    android.permission.PACKAGE_USAGE_STATS不是正常的许可,因此不能简单地请求.要检查是否已授予权限,请检查:

    AppOpsManager appOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
    int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
            android.os.Process.myUid(), getPackageName());
    if (mode == AppOpsManager.MODE_ALLOWED) {
        return true;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    要获得此许可,只需致电Intent:

    Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
    startActivity(intent);
    
    Run Code Online (Sandbox Code Playgroud)

    还需要另外一个许可:Manifest.permission.READ_PHONE_STATE.但是,这是正常的权限,因此可以像任何其他权限一样请求

  3. 用途NetworkStatsManager:

    要获得它的参考,请致电:

    NetworkStatsManager networkStatsManager = (NetworkStatsManager) getApplicationContext().getSystemService(Context.NETWORK_STATS_SERVICE);
    
    Run Code Online (Sandbox Code Playgroud)

    从中检索到的所有内容都NetworkStatsManager被打包进去Buckets.这只是一个简单的POJO,它保存数据.

    全球:

    要获得WiFi的整体使用情况:

    NetworkStats.Bucket bucket;
    try {
        bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI,
                "",
                0,
                System.currentTimeMillis());
    } catch (RemoteException e) {
        return -1;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    from NetworkStats.Bucket,可以调用两个方法来获取用法(以Bps为单位):

    bucket.getRxBytes();
    bucket.getTxBytes();
    
    Run Code Online (Sandbox Code Playgroud)

    获取移动网络的数据更加困难.为了获得Bucket通话:

    public long getAllRxBytesMobile(Context context) {
        NetworkStats.Bucket bucket;
        try {
            bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE,
                getSubscriberId(context, ConnectivityManager.TYPE_MOBILE),
                0,
                System.currentTimeMillis());
        } catch (RemoteException e) {
            return -1;
        }
        return bucket.getRxBytes();
    }
    
    //Here Manifest.permission.READ_PHONE_STATS is needed
    private String getSubscriberId(Context context, int networkType) {
        if (ConnectivityManager.TYPE_MOBILE == networkType) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            return tm.getSubscriberId();
        }
        return "";
    }
    
    Run Code Online (Sandbox Code Playgroud)

    应用:

    要获取特定应用程序的数据,请阅读queryDetailsForUID的文档.

    要获取WiFi的包使用情况:

    NetworkStats networkStats = null;
    try {
        networkStats = networkStatsManager.queryDetailsForUid(
                ConnectivityManager.TYPE_WIFI,
                "",
                0,
                System.currentTimeMillis(),
                packageUid);
    } catch (RemoteException e) {
        return -1;
    }
    NetworkStats.Bucket bucket = new NetworkStats.Bucket();
    networkStats.getNextBucket(bucket);
    
    Run Code Online (Sandbox Code Playgroud)

    获取Mobile的包使用情况:

    NetworkStats networkStats = null;
    try {
        networkStats = networkStatsManager.queryDetailsForUid(
                ConnectivityManager.TYPE_MOBILE,
                getSubscriberId(context, ConnectivityManager.TYPE_MOBILE),
                0,
                System.currentTimeMillis(),
                packageUid);
    } catch (RemoteException e) {
        return -1;
    }
    NetworkStats.Bucket bucket = new NetworkStats.Bucket();
    networkStats.getNextBucket(bucket);
    
    Run Code Online (Sandbox Code Playgroud)

    不幸的是,根据这段代码获取统计数据只能用于ConnectivityManager.TYPE_MOBILEConnectivityManager.TYPE_WIFI.

制作了一个示例Github repo演示用法.


dan*_*esz 8

还有一种获取统计信息的复杂方法,但这适用于所有适配器:(但它很昂贵,因为你必须不断读取文件),

  1. 在这里,您可以看到所有适配器和发送/接收的数据:
cat /proc/net/dev
Run Code Online (Sandbox Code Playgroud)
  1. 您可以从这些文件获取每个适配器的统计信息
cat /sys/class/net/**wlan0**/statistics/**rx**_bytes
Run Code Online (Sandbox Code Playgroud)

wlan0可能是您的所有适配器,但您需要在应用程序中维护该值,因为如果您关闭/打开适配器,该值将再次为0.(您可以拥有RX和TX值)

  1. 您可以获取当前正在发送/接收的应用列表
cat /proc/net/**tcp6**
Run Code Online (Sandbox Code Playgroud)

这也可以使用tcp,tcp6,upd,upd6来完成

这里有"uid"列,它是已安装应用的UID.(所以应用程序现在正在使用网络)

从该文件中,您还可以看到连接端点.

  1. 检查每个应用程序的发送/接收字节数(如TrafficStats API调用)
cat /proc/uid_stat/**10348**/tcp_snd
Run Code Online (Sandbox Code Playgroud)

这里的id是应用程序UID.你有send:tcp_snd和收到的:tcp_rcv文件.

  1. 您还可以执行一些进程和UID匹配:
cat /proc/**17621**/status
Run Code Online (Sandbox Code Playgroud)

这里的id是你可以从例如top命令获得的进程id .在状态文件中,您将拥有UID,即已安装/系统应用程序UID.

+1.你也可以看看这个文件,TrafficStats API使用这个:

cat /proc/net/xt_qtaguid/stats
Run Code Online (Sandbox Code Playgroud)

头:

idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
Run Code Online (Sandbox Code Playgroud)

价值观:

6 eth0 0x0 10005 0 0 0 80 2 0 0 0 0 0 0 80 2 0 0 0 0
7 eth0 0x0 10005 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8 eth0 0x0 10007 0 11133 25 4751 24 11133 25 0 0 0 0 4751 24 0 0 0 0
9 eth0 0x0 10007 1 5965514 4358 102028 2327 5965514 4358 0 0 0 0 102028 2327 0 0 0 0
10 eth0 0x0 10014 0 95 1 40 1 95 1 0 0 0 0 40 1 0 0 0 0
Run Code Online (Sandbox Code Playgroud)

因此,将第一个答案与这些知识混合起来,您可以获得更多更好的统计数据.