Как получить правильное количество байтов, отправленных и полученных в TrafficStats?
Мое приложение пытается подсчитать количество байтов, отправленных и полученных через 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;
Я чувствую, что приведенный выше алгоритм является разумным, однако я не уверен, как проверить точность этих счетчиков. Например, когда я попытался загрузить файл размером 2,7 МБ в Dropbox через WiFi, currentMobileSent
значение, которое я получил, было около 10 МБ. И даже не просматривая веб-страницы до следующей проверки, я получаю ненулевые значения, указывающие, что я получил некоторые байты данных за период ожидания.
Есть ли способ для меня, чтобы проверить, как TrafficStats
приходит на эти цифры? Я знаю, что помимо моего браузера, в фоновом режиме могут работать другие приложения, которые подключаются к Интернету, но от 2,7 МБ до 10 МБ кажется огромным скачком - я даже "получил" 90 МБ один раз, ничего не делая. Или что-то не так с тем, как я вычисляю байты, отправленные и полученные?
1 ответ
От TechRepublic:
Создайте новый проект Android в Eclipse. Не забудьте использовать класс TrafficStats, вы должны использовать API для Android 2.2 (Froyo) или выше.
в
/res/layout
папку мы создадим ресурс activity_main.xml. Для этого проекта мы просто используем серию текстовых представлений в вертикальной линейной компоновке.
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. Давайте также продолжим и объявим три переменные частного класса.
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;
}
Мы будем использовать переопределение при создании для инициализации наших личных переменных, а также запланировать обратный вызов в потоке пользовательского интерфейса. Запишите проверку для перечисления 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);
}
};