最近無聊看了關於android流量監控方面的知識,發覺android在這方面做得很是全面,google已經將對於流量監控類TrafficStats都封裝好了,非常容易上手,對於學習android開發的人來說,無疑是極大的利器。
先此聲明:以下的例子大部分來自於網路(就是我學流量監控的時候,在網上找的例子),但個人覺得,例子本身寫得非常棒,所以自己稍作修改拿來擺上架~~~呵呵呵呵呵。
好了,廢話不多說,轉入正題。
在看代碼前,先說明一下android怎樣統計手機內的流量的使用方式的呢?其實,
Android是基於linux的一個作業系統。
在Android中,你用Root Explorer去查看系統檔案的話,與流量監控相關的會有這麼幾個檔案/proc/net/dev這個檔案中具體記錄的暫時不是非常清楚,可能是整個系統的一個流量情況。
/proc/uid_stat/%d" 和"/proc/uid_stat/%d" %d為進程的UID。這個檔案裡只有兩項資料tcp_rcv和tcp_snd。
看命名大家應該就能看出代表什麼,一個代表總的接受位元組數,一個代表總的發送位元組數。
這兩個檔案為非標準linux核心檔案,由android核心層/kernel/net/Socket.c 的__sock_sendmsg函數負責寫入, 使用者層通訊端通訊在核心層最終會調用此函數 (包括本地通訊端和網路通訊端)。
而Android在2.3之前是沒有封裝響應的流量監控API的。在2.3之後呢,把資料流量監控封裝到了Android.net.TrafficStats類中。其原理就是讀取上文提到的那幾處檔案。其中有的方法也是讀取的別的檔案。
先讓我們來看一下設定檔,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" > <Button android:id="@+id/showList" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="顯示當前程式流量"/></LinearLayout>
設定檔非常的簡單,只是定義了一個Button組件,其id為showList
好了,再來看一下activity內的代碼
public class TrafficStatsActivity extends Activity { /** Called when the activity is first created. */private Button showBtn=null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); showBtn=(Button) findViewById(R.id.showList); showBtn.setOnClickListener(new ButtonListener()); } public void getAppTrafficList(){ //擷取所有的安裝在手機上的應用軟體的資訊,並且擷取這些軟體裡面的許可權資訊 PackageManager pm=getPackageManager();//擷取系統應用程式套件管理 //擷取每個包內的androidmanifest.xml資訊,它的許可權等等 List<PackageInfo> pinfos=pm.getInstalledPackages (PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS); //遍曆每個應用程式套件資訊 for(PackageInfo info:pinfos){ //請求每個程式包對應的androidManifest.xml裡面的許可權 String[] premissions=info.requestedPermissions; if(premissions!=null && premissions.length>0){ //找出需要網路服務的應用程式 for(String premission : premissions){ if("android.permission.INTERNET".equals(premission)){ //擷取每個應用程式在作業系統內的進程id int uId=info.applicationInfo.uid; //如果返回-1,代表不支援使用該方法,注意必須是2.2以上的 long rx=TrafficStats.getUidRxBytes(uId); //如果返回-1,代表不支援使用該方法,注意必須是2.2以上的 long tx=TrafficStats.getUidTxBytes(uId); if(rx<0 || tx<0){ continue; }else{ Toast.makeText(this, info.applicationInfo.loadLabel(pm)+"消耗的流量--"+ Formatter.formatFileSize(this, rx+tx), Toast.LENGTH_SHORT); } } } } } } private class ButtonListener implements OnClickListener{@Overridepublic void onClick(View v) {// TODO Auto-generated method stubgetAppTrafficList();} }}
這裡要注意的是這三句代碼:
//擷取每個應用程式在作業系統內的進程idint uId=info.applicationInfo.uid;//如果返回-1,代表不支援使用該方法,注意必須是2.2以上的long rx=TrafficStats.getUidRxBytes(uId);//如果返回-1,代表不支援使用該方法,注意必須是2.2以上的long tx=TrafficStats.getUidTxBytes(uId);
頭一句代碼主要的作用是擷取聲明到的網路許可權的application的進程系統id,就類似與我們window下的進程PID。
而第二句的作用毫無疑問的就是根據該進程的id擷取到改應用程式開機到現在從網路上接收到的位元組(以KB為單位),最後一句則是根據該進程的id擷取到改應用程式開機到現在向網路上發送的位元組(以KB為單位)。好了其他的也就沒什麼了。一些代碼我也子啊程式內注有注釋了。最後說一句,TrafficStats這個類只能在android2.2以上的版本才能夠使用,還有,測試的時候最好用真機來測試。因為模擬器的話,可能會造成rx和tx這兩個參數總為-1.
^ _^