我的应用程序试图计算通过WiFi/LAN和移动数据连接发送和接收的字节数。为此,我在某个时间点获取TrafficStats计数器的值,并在下次检查时从其值中减去该值。

// get current values of counters
long currentMobileTxBytes = TrafficStats.getMobileTxBytes();
long currentMobileRxBytes = TrafficStats.getMobileRxBytes();
long totalTxBytes = TrafficStats.getTotalTxBytes();
long totalRxBytes = TrafficStats.getTotalRxBytes();

// to get mobile data count, subtract old from current
long currentMobileSent = currentMobileTxBytes - oldMobileTxBytes;
long currentMobileReceived = currentMobileRxBytes - oldMobileRxBytes;

// to get WiFi/LAN data count, subtract total from mobile
long currentNetworkSent = totalTxBytes - currentMobileTxBytes;
long currentNetworkReceived = totalRxBytes - currentMobileRxBytes;

我认为上述算法是合理的,但是,我不确定如何检查这些计数器的准确性。例如,当我尝试通过WiFi将2.7MB的文件上传到Dropbox时,我得到的currentMobileSent值约为10MB。即使在下次检查之前都没有上网,我还是得到了非零值,表明我在等待期间确实收到了一些字节的数据。

我有办法检查TrafficStats如何到达这些数字吗?我知道,除了我的浏览器之外,可能还会有其他应用程序在后台运行并连接到Internet,但是2.7MB到10MB似乎是一个巨大的飞跃,我什至“接收”了90MB却什么也没做。还是我计算发送和接收的字节的方式有问题?

最佳答案

TechRepublic:

  • 在Eclipse中创建一个新的Android项目。请记住,要使用TrafficStats类,您必须将Android 2.2(Froyo)的API定位为目标,或者
    更高。
  • /res/layout文件夹中,我们将创建一个activity_main.xml资源。对于这个项目,我们只是在垂直方向使用一系列文本 View
    堆叠的线性布局。

  • activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:orientation="vertical">
    
       <TextView
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:gravity="center"
           android:paddingBottom="20dip"
           android:text="Traffic Stats Demo"
           android:textSize="16sp"
           android:textStyle="bold" />
    
       <TextView
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:gravity="center"
           android:text="Transmit Bytes"
           android:textColor="#00ff00"
           android:textSize="14sp" />
    
       <TextView
           android:id="@+id/TX"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:gravity="center"
           android:text="0"
           android:textSize="14sp" />
    
       <TextView
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:gravity="center"
           android:text="Receive Bytes"
           android:textColor="#ff0000"
           android:textSize="14sp" />
    
       <TextView
           android:id="@+id/RX"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:gravity="center"
           android:text="0"
           android:textSize="14sp" />
    </LinearLayout>
    

    放置好布局后,我们可以转到/src文件夹。创造
    MainActivity.java通过扩展Activity/AppCompatActivity类。我们也继续
    声明三个私有(private)类变量。

    MainActivity.java
    package com.authorwjf;
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.net.TrafficStats;
    import android.os.Bundle;
    import android.os.Handler;
    import android.widget.TextView;
    
    public class Main extends Activity {
        private Handler mHandler = new Handler();
        private long mStartRX = 0;
        private long mStartTX = 0;
    }
    

    我们将使用on create覆盖初始化私有(private)数据
    变量,以及安排UI线程上的回调。做一个
    枚举TrafficStats.UNSUPPORTED的检查记录。而我的
    TrafficStats类的使用经验一帆风顺,
    Google的官方文档指出某些设备可能不支持
    这种类型的报告,并且在这种情况下,调用会返回
    上述值。因此,最好将您的
    正如我在此处演示的那样,防御性地编写代码。

    MainActivity.java
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mStartRX = TrafficStats.getTotalRxBytes();
        mStartTX = TrafficStats.getTotalTxBytes();
    
        if (mStartRX == TrafficStats.UNSUPPORTED || mStartTX == TrafficStats.UNSUPPORTED) {
            AlertDialog.Builder alert = new AlertDialog.Builder(this);
            alert.setTitle("Uh Oh!");
            alert.setMessage("Your device does not support traffic stat monitoring.");
            alert.show();
        } else {
            mHandler.postDelayed(mRunnable, 1000);
        }
    }
    

    最后但并非最不重要的一点是,我们需要更新显示并重新安排
    可运行的。

    MainActivity.java
    private final Runnable mRunnable = new Runnable() {
        public void run() {
            TextView RX = (TextView) findViewById(R.id.RX);
            TextView TX = (TextView) findViewById(R.id.TX);
            long rxBytes = TrafficStats.getTotalRxBytes() - mStartRX;
            RX.setText(Long.toString(rxBytes));
            long txBytes = TrafficStats.getTotalTxBytes() - mStartTX;
            TX.setText(Long.toString(txBytes));
            mHandler.postDelayed(mRunnable, 1000);
        }
    };
    

    10-05 23:23