Android之TrafficStats实现流量实时监测
TrafficStats類是由Android提供的一個從你的手機(jī)開機(jī)開始,累計到現(xiàn)在使用的流量總量,或者統(tǒng)計某個或多個進(jìn)程或應(yīng)用所使用的流量,當(dāng)然這個流量包括的Wifi和移動數(shù)據(jù)網(wǎng)Gprs。這里只針對手機(jī)所使用的流量作介紹,至于統(tǒng)計某個進(jìn)程應(yīng)用使用的流量,道理都差不多,小伙伴們可以自己查下文檔。首先先介紹一下TrafficStats常用的一些方法:
TrafficStats.getTotalRxBytes() ——獲取從此次開機(jī)起總接受流量(流量是分為上傳與下載兩類的,當(dāng)然其實這里還有本地文件之間數(shù)據(jù)交換的流量,這個暫且不說,等下說明一下我遇到的問題);
TrafficStats.getTotalTxBytes()——獲取從此次開機(jī)起總發(fā)送流量;
TrafficStats.getMobileRxBytes()——獲取從此次開機(jī)起不包括Wifi的接受流量,即只統(tǒng)計數(shù)據(jù)網(wǎng)Gprs接受的流量;
TrafficStats.getMobileTxBytes()——獲取從此次開機(jī)起不包括Wifi的發(fā)送流量,即只統(tǒng)計數(shù)據(jù)網(wǎng)Gprs發(fā)送的流量;
于是,小伙伴們可以用getTotalRxBytes() - getMobileRxBytes()獲取手機(jī)Wifi的接受流量,同理獲得Wifi的發(fā)送流量。
那么,現(xiàn)在問題來了(不說挖掘機(jī),畢竟藍(lán)翔強(qiáng)):我上面所說的幾個方法都是統(tǒng)計從手機(jī)開機(jī)到現(xiàn)在所使用的總流量,而我需要實現(xiàn)的是檢測手機(jī)的實時流量使用,或者說我還要算出此刻的網(wǎng)速。那該咋辦呢?
這當(dāng)然也難不了小伙伴們的,我是這樣實現(xiàn)的:先獲取此刻的總流量,譬如說00:00:00時刻的總使用流量,然后再統(tǒng)計00:00:01時刻的總使用流量,那么兩者相減便是這1秒鐘所使用的流量,當(dāng)然你也可以設(shè)定為零點(diǎn)幾秒。我這里是用線程來實現(xiàn)的,當(dāng)然你們也可以用Timer,定時器之類的途徑實現(xiàn)。
1.先寫一個方法,用于統(tǒng)計Wifi下使用的流量:
public double getWifiTraffic(double time){
double rtotalGprs = TrafficStats.getTotalRxBytes();
double ttotalGprs = TrafficStats.getTotalTxBytes();
double rgprs = TrafficStats.getMobileRxBytes();
double tgprs = TrafficStats.getMobileTxBytes();
double rwifi = rtotalGprs - rgprs;
double twifi = ttotalGprs - tgprs;
totalWifi = rwifi + twifi;
return totalWifi;
}
2.用一個TextView來顯示一下我們統(tǒng)計的流量數(shù)據(jù):
?
3.然后我們新建一個線程用handler更新UI:
new Thread(new Runnable() {
@Override
public void run() {
while(true){
//獲取當(dāng)前時刻
double currentTime = System.currentTimeMillis();
// getWifiTraffic(currentTime);
獲取當(dāng)前時刻的Wifi流量
double totalWifi01 = getWifiTraffic(currentTime);
//讓線程休眠1秒鐘
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//獲取1秒鐘之后的時刻
double frontTime = System.currentTimeMillis();
// 獲取一秒鐘之后時刻所對應(yīng)的Wifi使用流量
double totalWifi02 = getWifiTraffic(frontTime);
//兩者相減得到這1秒鐘所產(chǎn)生的Wifi流量
double errorTraffic = totalWifi02 - totalWifi01;
//這里之所以有一個流量<512b,不將其計入流量統(tǒng)計的原因就是由于我前面提及的本地進(jìn)程產(chǎn)生的本地流量,如果不減的話,你會發(fā)現(xiàn)Android會把不聯(lián)網(wǎng)狀態(tài)下
//本地進(jìn)程之間交互的本地流量也計算進(jìn)去,我測試了一下大概在每秒鐘200b左右
if(errorTraffic < 512){
errorTraffic = 1;
}
//將byte轉(zhuǎn)化為為Mb,1048576=1024*1024,只不過在實際統(tǒng)計中計算會有少許偏差,小伙伴們可根據(jù)實際情況微調(diào)
wf += errorTraffic/1048576;
wifiTraffic = df.format(wf);
// Log.i("使用的流量", wifiTraffic + "");
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
}
}).start();
?
final Handler handler = new Handler{
public void handleMessage(Message msg){
super.handleMessage(msg);
if(msg.what == 1){
//當(dāng)流量小于1時,由于0.5這樣的數(shù)我們會看到手機(jī)上會顯示為.5,因此在前面加一個0以顯示完整
if(Double.parseDouble(wifiTraffic) < 1){
tv.setText("0" + wifiTraffic + "MB");
}
else{
tv.setText(wifiTraffic + "MB");
}
}
}
};
下面貼一下整段代碼:
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.TrafficStats;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
double totalWifi;
public static String wifiTraffic ;
public static double wf =0;
private TextView textView;
private WifiManager wifiManager;
public static int wifiStr;
DecimalFormat df = new DecimalFormat(".##");
private TextView tv;
private Handler handler1= null;
int hours = 0,minutes = 0,seconds = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.textView);
wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
wifiStr = wifiManager.getWifiState();
if(wifiStr != 3){
Toast.makeText(this, "Wifi未連接", 1000).show();
}
if(wifiStr == 3){
final Handler handler = new Handler(){
public void handleMessage(Message msg){
super.handleMessage(msg);
if(msg.what == 1){
if(Double.parseDouble(wifiTraffic) < 1){
Log.i("wifiTraffic", wifiTraffic);
textView.setText("0" + wifiTraffic + "MB");
}
else{
textView.setText(wifiTraffic + "MB");
}
}
}
};
tv = (TextView)findViewById(R.id.tv3);
if(wifiStr == 3){
handler1 = new Handler(){
public void handleMessage(Message msg1){
super.handleMessage(msg1);
if(msg1.what == 1){
tv.setText(new DecimalFormat("00").format(hours) + ":" +?
new DecimalFormat("00").format(minutes) + ":" + new DecimalFormat("00").format(seconds));
}
}
};
}
new Thread(new Runnable() {
public void run(){
for(int i = 0;;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
seconds++;
Message msg1 = new Message();
msg1.what = 1;
handler1.sendMessage(msg1);
if(seconds == 60){
seconds = 0;
minutes++;
if(minutes == 60){
minutes = 0;
hours++;
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
double currentTime = System.currentTimeMillis();
// getWifiTraffic(currentTime);
double totalWifi01 = getWifiTraffic(currentTime);;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
double frontTime = System.currentTimeMillis();
// getWifiTraffic(frontTime);
double totalWifi02 = getWifiTraffic(frontTime);
double errorTraffic = totalWifi02 - totalWifi01;
if(errorTraffic < 512){
errorTraffic = 1;
}
wf += errorTraffic/1111500;
wifiTraffic = df.format(wf);
// Log.i("使用的流量", wifiTraffic + "");
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
}
}).start();
}
}
public double getWifiTraffic(double time){
double rtotalGprs = TrafficStats.getTotalRxBytes();
double ttotalGprs = TrafficStats.getTotalTxBytes();
double rgprs = TrafficStats.getMobileRxBytes();
double tgprs = TrafficStats.getMobileTxBytes();
double rwifi = rtotalGprs - rgprs;
double twifi = ttotalGprs - tgprs;
totalWifi = rwifi + twifi;
return totalWifi;
//totalWifi = rtotalGprs + ttotalGprs;
}
}
1、TrafficStats類的使用
以下結(jié)論,是自己真機(jī)實測的結(jié)果,與自己在網(wǎng)上看到的不同,大家可自測驗證。
(1)getMobile...方法,獲取Gprs/3G流量
(2)getTotal...方法,獲取Gprs/3G+Wifi的流量
以上兩類方法統(tǒng)計的都是,從打開網(wǎng)絡(luò)開始,到關(guān)閉網(wǎng)絡(luò),這一段時間內(nèi)使用的流量。例如:10點(diǎn)打開,11點(diǎn)關(guān)閉,那么getMobileRxBytes方法,回返的是這段時間內(nèi)Gprs/3G接受到的字節(jié)數(shù)。
(3)getUid...方法,獲取某個網(wǎng)絡(luò)UID的流量。這類方法,返回的是,從開機(jī)到關(guān)機(jī),某個網(wǎng)絡(luò)UID(我理解就是某個應(yīng)用,如果不對,請在評論中指正)使用的Gprs/3G+Wifi的流量
2、getUid...方法的使用
以下這段代碼是網(wǎng)上找的,出處找不到了,希望原作者不要介意啊
List<PackageInfo> packinfos = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS); for (PackageInfo info : packinfos) { String[] premissions = info.requestedPermissions; if (premissions != null && premissions.length > 0) { for (String premission : premissions) { if ("android.permission.INTERNET".equals(premission)) { // System.out.println(info.packageName+"訪問網(wǎng)絡(luò)"); int uid = info.applicationInfo.uid; long rx = TrafficStats.getUidRxBytes(uid); long tx = TrafficStats.getUidTxBytes(uid); if (rx < 0 || tx < 0) { System.out.println(info.packageName + "沒有產(chǎn)生流量"); } else { System.out.println(info.packageName + "的流量信息:"); System.out.println("下載的流量" + Formatter.formatFileSize(this, rx)); System.out.println("上傳的流量" + Formatter.formatFileSize(this, tx)); } } } System.out.println("---------"); } } 3、獲取流量信息的Service類(1)因為兩個廣播都需要動態(tài)注冊,所以寫成了Service
(2)getMobile...和getTotal...方法獲取的都是從打開網(wǎng)絡(luò)開始,到關(guān)閉網(wǎng)絡(luò),這一段時間內(nèi)使用的流量。
因此要在網(wǎng)絡(luò)正在關(guān)閉時獲取的就是這段時間的流量,WifiManager.WIFI_STATE_DISABLING表示的就是這個狀態(tài)
(3)Gprs/3G貌似沒有類似的狀態(tài),可以被監(jiān)控到,只有,State.CONNECTED和State.DISCONNECTED。但是處于State.DISCONNECTED這個狀態(tài)時,getMobile...方法獲取到的值就都是0了
所有,我不得不在State.CONNECTED這個狀態(tài)開始時,開啟線程用于獲取Gprs/3G的流量,直到我獲取的到數(shù)據(jù)為0時,保存上一次的數(shù)據(jù)。
如果大家有更好的方法,請務(wù)必告訴我啊!
package forrest.forassist.service; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.NetworkInfo.State; import android.net.TrafficStats; import android.net.wifi.WifiManager; import android.os.IBinder; import android.text.format.Formatter; import android.util.Log; import forrest.forassist.db.MySQLiteDatabase; import forrest.forassist.utils.Util; public class TrafficService extends Service { private TrafficReceiver tReceiver; private WifiManager wifiManager; private ConnectivityManager cManager; public IBinder onBind(Intent intent) { return null; } public void onCreate() { // WifiManager,ConnectivityManager wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE); cManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); // 注冊TrafficReceiver tReceiver = new TrafficReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(tReceiver, filter); super.onCreate(); } public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } private class TrafficReceiver extends BroadcastReceiver { private String action = ""; private static final String TAG = "TrafficReceiver"; long mobileRx; long mobileTx; public void onReceive(Context context, Intent intent) { action = intent.getAction(); if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { if (wifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLING) { Log.i(TAG, "WIFI_STATE_DISABLING"); long wifiDown = TrafficStats.getTotalRxBytes() - TrafficStats.getMobileRxBytes(); long wifiUp = TrafficStats.getTotalTxBytes() - TrafficStats.getMobileTxBytes(); MySQLiteDatabase sqLite = new MySQLiteDatabase(context); // 打開數(shù)據(jù)庫 sqLite.insertWifi(Util.todayDate, wifiDown, wifiUp); sqLite.closeDB(); Log.i(TAG, "wifi下載流量" + Formatter.formatFileSize(context, wifiDown)); Log.i(TAG, "wifi上傳流量" + Formatter.formatFileSize(context, wifiUp)); } } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { Log.i(TAG, "CONNECTIVITY_ACTION"); NetworkInfo networkInfo = cManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); State state = networkInfo.getState(); if (state == State.CONNECTED) { Log.i(TAG, "State.CONNECTED"); // 開始不斷獲取最近的流量信息,值為0時,跳過 new Thread() { public void run() { long mobileRxType = TrafficStats.getMobileRxBytes(); long mobileTxType = TrafficStats.getMobileTxBytes(); if (mobileRxType + mobileTxType != 0) { try { mobileRx = mobileRxType; mobileTx = mobileTxType; Log.i(TAG, "mobileRx:" + mobileRx); Log.i(TAG, "mobileTx:" + mobileTx); Thread.sleep(1000); run(); } catch (InterruptedException e) { e.printStackTrace(); } } else { // 寫入數(shù)據(jù)庫 Log.i(TAG, "寫入數(shù)據(jù)庫"); MySQLiteDatabase sqLite = new MySQLiteDatabase(TrafficService.this); sqLite.insertGprs(Util.todayDate, mobileRx, mobileTx); sqLite.closeDB(); } }; }.start(); } } } } public void onDestroy() { unregisterReceiver(tReceiver); super.onDestroy(); } }
總結(jié)
以上是生活随笔為你收集整理的Android之TrafficStats实现流量实时监测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android之电源管理 PowerMa
- 下一篇: Android之android.os.N