0
点赞
收藏
分享

微信扫一扫

Android应用的流量统计方法

Sikj_6590 2022-03-12 阅读 44
android

通过shell读取

1.获取应用的userId

adb shell dumpsys package tv.danmaku.ijk.media.example |grep userId

2.根据userId查询/proc/net/xt_qtaguid/stats文件

adb shell cat /proc/net/xt_qtaguid/stats | grep 10156

之后会得到类似如下输出:

idx|iface|acct_tag_hex|uid_tag_int|cnt_set|rx_btyes|rx_packets|tx_bytes|tx_packets

72  wlan0     0x0        10156        0     186540     132       3632       55      186540       132     0 0 0 0 3632     55     0 0 0 0

73  wlan0     0x0        10156        1   2207630028  1505126  38140468   640292    2207630028   1505126 0 0 0 0 38140468 640292 0 0 0 0

其中rx_bytes代表接收的总字节数,tx_bytes代表发送的总字节数。

在开始统计时获取一次上述数据,结束时再获取一次,二者作差即可得到应用在这段时间使用的流量。

在应用内获取

使用Android NetworkStatsManager类获取应用的流量信息,官方文档地址NetworkStatsManager  |  Android Developers

1.在AndroidManifest.xml中添加如下权限

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

2.Android6以后的机型需要动态申请权限

if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {

    ActivityCompat.requestPermissions(thisnew String[]{Manifest.permission.READ_PHONE_STATE}, MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);

}

3.查询流量情况

if (mEndTime > mStartTime && mUid > 0 && Build.VERSION.SDK_INT >= 23) {

    final AppOpsManager appOps = (AppOpsManager) mAppContext.getSystemService(Context.APP_OPS_SERVICE);

    NetworkStatsManager networkStatsManager = (NetworkStatsManager) mAppContext.getSystemService(Context.NETWORK_STATS_SERVICE);

    TelephonyManager tm = (TelephonyManager) mAppContext.getSystemService(Context.TELEPHONY_SERVICE);

    String subId = tm.getSubscriberId();

    NetworkStats summaryStats;

    long summaryRx = 0;

    NetworkStats.Bucket summaryBucket = new NetworkStats.Bucket();

    try {

        summaryStats = networkStatsManager.querySummary(ConnectivityManager.TYPE_WIFI, subId, mStartTime, mEndTime);

        do {

            summaryStats.getNextBucket(summaryBucket);

            int summaryUid = summaryBucket.getUid();

            if (mUid == summaryUid) {

                summaryRx += summaryBucket.getRxBytes();

            }

        while (summaryStats.hasNextBucket());

        Log.i(TAG, "[BandWidth] uid: " + mUid + ", rx: " + summaryRx + ", timediff: " + (mEndTime - mStartTime) +", speed: " + summaryRx / (mEndTime - mStartTime) + "KB/s");

    catch (Exception e) {

        e.printStackTrace();

    }

}

注:实测querySummary的startTime和endTime参数是不生效的,最终返回的值不是该应用在startTime到endTime这段时间内的流量,而是1小时内(如4点到5点)的流量数据。因此我们统计流量时也需要和shell方法一样,在开始时获取一次,结束时再获取一次,二者作差得到这段时间的流量数据。

实验对比

分别通过shell命令和NetworkStatsManager获取两次应用的流量情况,结果如下

//shell第一次

72 wlan0 0x0 10156 0 186540 132 3632 55 186540 132 0 0 0 0 3632 55 0 0 0 0

73 wlan0 0x0 10156 1 3725054960 2529375 59168244 980059 3725054960 2529375 0 0 0 0 59168244 980059 0 0 0 0

//shell第二次

72 wlan0 0x0 10156 0 186540 132 3632 55 186540 132 0 0 0 0 3632 55 0 0 0 0

73 wlan0 0x0 10156 1 3760814288 2553440 59955225 991975 3760814288 2553440 0 0 0 0 59955225 991975 0 0 0 0

//NetworkStatsManager第一次

2022-03-09 15:31:50.944 878-878/tv.danmaku.ijk.media.example I/IjkVideoView: [BandWidth] uid: 10156, rx: 53477797, timediff: 1210, speed: 44196KB/s

//NetworkStatsManager第二次

2022-03-09 15:38:07.416 878-878/tv.danmaku.ijk.media.example I/IjkVideoView: [BandWidth] uid: 10156, rx: 89237125, timediff: 204509, speed: 436KB/s

这段时间内读取的bytes分别为3760814288 - 3725054960 = 89237125 - 53477797 = 35759328,两种方法统计的数据是完全一致的,对比Android手机自带的流量监控工具,数据同样能够匹配上。

举报

相关推荐

0 条评论