Android 流量统计

Android 流量统计

最近项目上有一个应用流量统计的功能需要实现,在此总结一下

流量统计架构

在这里插入图片描述

Android9.0之前,流量监控是基于xt_qtaguid模块的,通过读取/proc/net/xt_qtaguid/stats文件内容进行解析获取对应流量数据。

Android9.0之后,改为基于eBPF的网络监控模块,更加灵活且更易于维护;Android9.0 通过读取/sys/fs/bpf/traffic_uid_stats_map获取数据;Android10.0通过读取/sys/fs/bpf/map_netd_app_uid_stats_map获取数据。

调试查看流量信息:

XXX:/ # dumpsys netd trafficcontroller

  TrafficController
    BPF module status: BPF_LEVEL_EXTENDED

    mCookieTagMap status: OK
    mUidCounterSetMap status: OK
    mAppUidStatsMap status: OK
    mStatsMapA status: OK
    mStatsMapB status: OK
    mIfaceIndexNameMap status: OK
    mIfaceStatsMap status: OK
    mConfigurationMap status: OK
    mUidOwnerMap status: OK

    Cgroup ingress program status: OK
    Cgroup egress program status: OK
    xt_bpf ingress program status: OK
    xt_bpf egress program status: OK
    xt_bpf bandwidth whitelist program status: OK
    xt_bpf bandwidth blacklist program status: OK

    BPF map content:

      mCookieTagMap:

      mUidCounterSetMap:
      1001 1
      1073 1
      1002 1
      10046 1
      1000 1
      10016 1
      1076 1
      10037 1
      10056 1
      10019 1

      mAppUidStatsMap::
      uid rxBytes rxPackets txBytes txPackets
      10020 11763 24 15904 37
      1076 324919 1159 208570 1326
      10036 171008 1213 143638 1239
      1051 19271 140 9751 154
      0 3106517 27677 3158691 28118
      10019 18591 30 5631 39
      1020 356303 1419 118037 454
      10045 19345 121 14092 167
      10037 16511616 13422 13875657 12921
      1000 3623643 35705 3038615 35624

      mStatsMapA:
      ifaceIndex ifaceName tag_hex uid_int cnt_set rxBytes rxPackets txBytes txPackets

      mStatsMapB:
      ifaceIndex ifaceName tag_hex uid_int cnt_set rxBytes rxPackets txBytes txPackets
      3 dummy0 0x0 0 0 0 0 152 2
      1 lo 0x0 1000 1 8232 98 8232 98
      3 dummy0 0x0 1020 0 1527 6 1527 6
      1 lo 0x0 1020 0 1176 6 1176 6

      mIfaceIndexNameMap:
      ifaceIndex=8 ifaceName=rmnet_ipa0
      ifaceIndex=6 ifaceName=sit0
      ifaceIndex=7 ifaceName=ip6tnl0
      ifaceIndex=4 ifaceName=ip_vti0
      ifaceIndex=2 ifaceName=bond0
      ifaceIndex=11 ifaceName=p2p0
      ifaceIndex=3 ifaceName=dummy0
      ifaceIndex=10 ifaceName=wlan0
      ifaceIndex=5 ifaceName=ip6_vti0
      ifaceIndex=1 ifaceName=lo

      mIfaceStatsMap::
      ifaceIndex ifaceName rxBytes rxPackets txBytes txPackets
      3 dummy0 50949 196 110002 501
      10 wlan0 4210802 7222 764069 6653
      1 lo 19812096 73362 19812096 73362

查询方法

这里主要介绍一下NetworkStatsManager的相关方法

TrafficStats

  • 获取所有网口总的统计数据
    • static long getTotalRxBytes() //返回设备启动后收到的字节数。
    • static long getTotalRxPackets() //返回设备启动后收到的数据包数量。
    • static long getTotalTxBytes() //返回设备启动后传输的字节数。
    • static long getTotalTxPackets() //返回设备启动后传输的数据包数量。
  • 根据UID获取统计数据
    • static long getUidRxBytes(int uid) //返回设备引导后给定UID收到的字节数。
    • static long getUidRxPackets(int uid) //返回设备启动后给定UID收到的数据包数量。
    • static long getUidTxBytes(int uid) //返回设备启动后收到的字节数。
    • static long getUidTxPackets(int uid) //返回设备启动后传输的数据包数量

NetworkStatsManager

通过UID查询单个应用
  1. 通过包名获取UID
    private static int getUidByPackageName(Context context, String packageName) {
        int uid = -1;
        PackageManager packageManager = context.getPackageManager();
        try {
            PackageInfo packageInfo = packageManager.getPackageInfo(packageName,
                PackageManager.GET_META_DATA);
            uid = packageInfo.applicationInfo.uid;
        } catch (PackageManager.NameNotFoundException ex) {
            ex.printStackTrace();
        }
        return uid;
    }
  1. 获取应用使用流量信息
    • 参数描述如下:
      • networkType 查询网络类型 (ConnectivityManager.TYPE_WIFIConnectivityManager.TYPE_MOBILE
      • subscriberId 设备唯一id(android 10及以后设备 获取不了,可不传)
      • startTime 查询指定时间段 开始时间戳
      • endTime 查询指定时间段 结束时间
      • uid 查询设备的Uid
NetworkStatsManager statsManager = (NetworkStatsManager) AccountApplication.getContext()
            .getSystemService(NETWORK_STATS_SERVICE);
        try (NetworkStats stats = statsManager.queryDetailsForUid(ConnectivityManager.TYPE_MOBILE,
            null, startTime, endTime, uid)) {
            NetworkStats.Bucket bucket = new NetworkStats.Bucket();
            stats.getNextBucket(bucket);
            totalSize = bucket.getRxBytes() + bucket.getTxBytes();
        }

问题

在使用queryDetailsForUid方法的过程中,发现获取到的数据为0,通过网上查阅才了解到,需要设置subscribeId为null而不是“”,源码中也有相关说明

  1. queryDetailsForUid(int networkType, String subscriberId,long startTime, long endTime, int uid)

在这里插入图片描述

  1. queryDetailsForUidTagState(int networkType, String subscriberId,long startTime, long endTime, int uid, int tag, int state)

  2. createTemplate(int networkType, String subscriberId)

在这里插入图片描述

这里可以看到传入null进行查询就可以了;

然后是查询APP今日使用流量,发现总是获取为0,后来通过查询时间改为次日即可正常查询出来,very good!

参考连接

  1. (2条消息) android 统计应用流量 NetworkStatsManager_android获取流量使用情况_北极的松树的博客-CSDN博客
  2. Android-流量统计 - Wxy的个人博客 (leo-wxy.github.io)
  3. NetworkStatsManager.java - OpenGrok cross reference for /frameworks/base/core/java/android/app/usage/NetworkStatsManager.java (aospxref.com)
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立花泷える宫水三叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值