【问题标题】:TrafficStats Api android and calculation of daily data usageTrafficStats Api android和每日数据使用量的计算
【发布时间】:2011-10-03 17:08:53
【问题描述】:

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

【问题讨论】:

  • 您是否尝试过仅进行一些日志记录并查看计数器是否/何时重置?我会假设计数器在创建进程时启动,并在进程完成时重置(即手机关闭)。
  • 感谢您的回答。手机关机后它的计数器设置为零。现在,我将继续基于正常运行时间计算数据使用量的下一步

标签: android networking usage-statistics android-data-usage


【解决方案1】:

这些是“自从接口启动以来”或“自从具有此 UID 的应用程序启动以来”的计数器。因此,假设您的手机进入“飞行模式”然后返回,计数器可能会再次从零开始。如果您需要每秒值,则需要每秒调用这些函数,然后使用上次调用的增量。如果 delta 为负数,直接使用该值,表示计数器再次从零开始。

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

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

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

【讨论】:

  • 总网络接口和只有移动网络接口有什么区别。getMobileRxBytes返回非常低的值,而getTotalRxBytes返回合理的值。
  • getMobileRxBytes 返回通过 3G/4G/GPRS 等接收的数据。getTotalRxBytes 包括通过 Wi-Fi 接收的所有数据。
  • 如何重置 Traffic Stats Api 的计数器。是否有任何系统调用。实际上,每次设备重启时,它都会删除较早的文件并创建新文件,从而在每次重启时设置新的计数器。我可以通过我的应用程序以编程方式进行吗
  • 谢谢。我是根据在单击重置时从上次存储的值中减去当前值来使其工作的
  • @haimg:对于当前的 API 版本 (20/21),it seems that TrafficStats count both TCP and UDP
【解决方案2】:

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

重要的一点是,这些计数器不包括数据包开销,只包括有效负载大小。所以通常这意味着 3-4% 的数据可能下落不明。但是,如果它是数据包有效负载较小的流式传输、洪流或 VoIP 应用程序,则可能会有更多的数据未计入。

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

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

【讨论】:

  • 这个答案真的正确吗? See here.
  • 我的回答已超过 6 年,并且在发布时是正确的。功能之间的数据包标头差异可能已得到纠正。我的建议是让您的应用程序下载已知文件大小并验证 UID API 返回的字节数是否大于文件大小,这将验证现在包含数据包头大小。请记住,不同操作系统版本的行为可能会有所不同,并且记录的行为与实际行为可能会有所不同。
【解决方案3】:

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

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";

}

【讨论】:

  • 你确定吗?它给了我所有安卓操作系统的数据统计?
  • 是的,为什么不呢。已经在play.google.com/store/apps/…实现了
  • 当我遇到 api 级别 23 时,它没有给我任何 MB 或 BYTES
  • 当我在牛轧糖和奇巧中安装你建议的应用程序时,我没有得到任何数据。应用显示“没有可用的应用!”。你能帮帮我吗?
  • 你为什么给 1 星?
【解决方案4】:

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

    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));

【讨论】:

    猜你喜欢
    • 2020-01-04
    • 1970-01-01
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多