关于网络:TrafficStats Api android和计算日常数据使用情况

TrafficStats Api android and calculation of daily data usage

对以下两种Android TrafficStats方法感到困惑:
getUidTxBytes(int uid)和getUidRxBytes(int uid),
这两种方法返回通过网络为此UID发送和接收的字节数。 但它的时间单位是多少,是每秒?
如果我想计算每个应用每天传输和接收的数据,我该怎么办。 我想过一种方法,在sql中存储数据并继续向表中添加数据。 这是正确的方法吗?


这些是计数器"因为接口上升"或"因为具有此UID的应用程序已启动"。所以说如果你的手机进入"飞行模式"然后再回来,计数器可能会再次从零开始。如果需要每秒的值,则需要每秒调用这些函数,然后使用上次调用的增量。如果delta是负数,只需按原样使用该值,这意味着计数器再次从零开始。

还有一件事:据我所知,这些计数器只计算TCP / IP。不是UDP。因此,如果您需要非常精确的记帐,并且有问题的应用程序使用UDP / IP或TCP之外的任何其他协议,这些计数器将是错误的。

有关此功能的工作原理,请查看免费提供的Android源代码。有问题的文件是./frameworks/base/core/jni/android_net_TrafficStats.cpp

此函数从/proc/uid_stat/[uid]/tcp_snd获取数据。如果您需要更多相关信息,您需要深入了解Linux内核......


这些计数器包含自上次重新引导以来的字节数。一些电话这些计数器可能会定期重置,但大部分时间它们只会在重启后重置。进入飞行模式或在移动和Wi-Fi之间切换不会重置这些计数器。

一个重要的一点是,这些计数器不包括数据包开销,只包括有效负载大小。因此,通常这意味着3-4%的数据可能无法计算。但是,如果它是数据包有效负载很小的流媒体,torrent或VoIP应用程序,则可能会有更多的数据未计入。

有趣的是,getTotalRxBytes(所有接口上的接收字节,移动和Wi-Fi组合)和getMobileRxBytes(仅在移动接口上接收的字节)包括所有字节,包括开销。基本上,您的应用字节数总计将小于您的接口字节数总计,因此小于网络运营商为您收费的数据量。

最后一点,大多数流媒体应用程序不会在自己的UID下考虑他们的数据。它们在system.media UID下计算。因此,如果您要监控YouTube的数据使用情况,那么该应用下只会显示非常少量的数据;其余的将在媒体UID(1013)下。


在这里,我获得了那些拥有互联网许可的应用程序,
您可以根据需要更改权限名称并获取应用程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
ArrayList<AppObject> listApps;

 public void getAllAppList() {

    listApps = new ArrayList<AppObject>();

    PackageManager p = getPackageManager();
    List<ApplicationInfo> packages = p.getInstalledApplications(PackageManager.GET_META_DATA);

    for (ApplicationInfo applicationInfo : packages) {

        try {

            PackageInfo packageInfo = p.getPackageInfo(applicationInfo.packageName, PackageManager.GET_PERMISSIONS);

            String[] permissions = packageInfo.requestedPermissions;

            for (String permissionName : permissions) {

                if (permissionName.equals("android.permission.INTERNET")) {

                    ApplicationInfo appInfo = packageInfo.applicationInfo;

                    AppObject appObject = new AppObject();

                    appObject.appDrawable = getPackageManager().getApplicationIcon(appInfo);
                    appObject.appName = (String) getPackageManager().getApplicationLabel(appInfo);
                    appObject.dataUsage = getDataUsage(appInfo);

                    listApps.add(appObject);

                }

            }
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }

    Debug.e("APP_SIZE",":" + listApps.size());

    appsAdapter.addAll(listApps);

}

public String getDataUsage(ApplicationInfo appInfo) {

    int uid = appInfo.uid;

    double received = (double) TrafficStats.getUidRxBytes(uid) / (1024 * 1024);
    double sent = (double) TrafficStats.getUidTxBytes(uid) / (1024 * 1024);

    double total = received + sent;

    return String.format("%.2f", total) +" MB";

}


getUidRxBytes()和getUidTxBytes()基本上分别用于接收和发送的字节。要监控每个应用程序的数据,只需找到每个进程的uid并找到每个进程的相应数据,这将是每个应用程序的数据,然后您可以使用此代码进行计算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    TextView totData = (TextView)findViewById(R.id.totData);

    TextView wifiTot = (TextView)findViewById(R.id.wifitotData);
    TextView wifiTX = (TextView)findViewById(R.id.wifiUpData);
    TextView wifiRX = (TextView)findViewById(R.id.wifiDownData);

    TextView mobileTot = (TextView)findViewById(R.id.mobtotData);
    TextView mobTX = (TextView)findViewById(R.id.mobUpData);
    TextView mobRX = (TextView)findViewById(R.id.mobDownData);

    /*
     * Converting bytes to MB
     */
    long rxBytes = TrafficStats.getTotalRxBytes()/1048576;
    long txBytes = TrafficStats.getTotalTxBytes()/1048576;

    long mobUpload = TrafficStats.getMobileTxBytes()/1048576;
    long mobDown = TrafficStats.getMobileRxBytes()/1048576;

    long wifiUpload = txBytes-(mobUpload);
    long wifiDown = rxBytes-(mobDown);

    wifiRX.setText(Long.toString(wifiDown));
    wifiTX.setText(Long.toString(wifiUpload));
    long wifitot = wifiUpload+wifiDown;
    wifiTot.setText(Long.toString(wifitot));

    mobTX.setText(Long.toString(mobUpload));
    mobRX.setText(Long.toString(mobDown));
    long mobTot = mobUpload+mobDown;
    mobileTot.setText(Long.toString(mobTot));

    totData.setText(Long.toString(wifitot+mobTot));