什么是網(wǎng)絡(luò)流量?
網(wǎng)絡(luò)流量是指,能夠連接網(wǎng)絡(luò)的設(shè)備在網(wǎng)絡(luò)上所產(chǎn)生的數(shù)據(jù)流量。
性能數(shù)據(jù)給出的網(wǎng)絡(luò)流量性能數(shù)據(jù)可以區(qū)分接收流量和發(fā)送流量:
接收流量:應(yīng)用運(yùn)行期間,網(wǎng)卡的下行流量,單位是字節(jié)
發(fā)送流量:應(yīng)用運(yùn)行期間,網(wǎng)卡的上行流量,單位是字節(jié)
方案介紹
讀取linux流量統(tǒng)計文件
利用Android流量統(tǒng)計API
Tcpdump抓包 + wireshark分析
讀取linux流量統(tǒng)計文件
1.讀取/proc/net/dev文件的方式
文件中記錄了整個系統(tǒng)的流量情況,示例結(jié)果如下:

其中最左側(cè)的是網(wǎng)絡(luò)接口名,Receive表示接收數(shù)據(jù),Transmit表示發(fā)送數(shù)據(jù):
bytes表示收發(fā)的字節(jié)數(shù)
packets表示收發(fā)正確的包量
errs表示收發(fā)錯誤的包量
drop表示收發(fā)丟棄的包量
圖中,wlan0是WIFI網(wǎng)絡(luò)使用的接口,而rmnet0是GPRS使用的接口。但是,并不是所有機(jī)器都是用wlan0來表示W(wǎng)IFI接口,同樣也不是所有rmnet0來表示GPRS,這些字段的表示都與ROM相關(guān)。甚至存在一些ROM中沒有/proc/net/dev文件。
但該統(tǒng)計方式更主要的問題是:
流量數(shù)據(jù)不區(qū)分應(yīng)用,實際獲取的是整個手機(jī)一段時間內(nèi)的流量情況,而非指定APP的
2. 讀取/sys/class/net目錄下數(shù)據(jù)的方式

找到相關(guān)類別的目錄,在其子目錄statistics下游可以通過rx_bytes和tx_bytes查看收發(fā)流量:

和/proc/net/dev一樣,這種方式也不區(qū)分應(yīng)用
3. 讀取/proc/net/xt_qtaguid/stats文件的方式
從/proc/net/xt_qtaguid/stats獲取網(wǎng)絡(luò)流量統(tǒng)計會更全面,Android機(jī)型兼容性更優(yōu)。實際上后面會提到,Android提供的流量統(tǒng)計API -TrafficStats中,對uid進(jìn)行流量統(tǒng)計的方法,底層就是讀取了該文件。

dx那行代表了文件頭,下面對應(yīng)的是數(shù)據(jù)。簡單介紹幾個我們比較關(guān)注的列:
iface代表網(wǎng)絡(luò)接口
acct_tag_hex代表socket
uid_tag_int是UID
cnt_set實際上就是一個標(biāo)志位,0代表前臺流量,1代表后臺流量
rx_bytes,r代表receive,是接收數(shù)據(jù)
tx_bytes,t代表transmit,是傳輸數(shù)據(jù)
其中第4列uid_tag_int是UID,第6和8列為rx_bytes(接收數(shù)據(jù))和tx_bytes(傳輸數(shù)據(jù))包含tcp,udp等所有網(wǎng)絡(luò)流量傳輸?shù)慕y(tǒng)計。

將所有UID相關(guān)的rx_bytes相加作為 應(yīng)用接收流量,tx_bytes相加作為 應(yīng)用發(fā)送流量。
獲取APP在當(dāng)前時刻的累計WIFI流量數(shù)值的偽代碼如下:

我們只需要間隔時間去獲取當(dāng)前APP的累計流量數(shù)據(jù),并計算差值,便可得到每小段時間內(nèi)的流量消耗;將整個測試期間的數(shù)據(jù)匯總,便可以得到網(wǎng)絡(luò)流量性能數(shù)據(jù)結(jié)果了。
利用Android流量統(tǒng)計API
TrafficStats
Android 2.2 版本開始加入了 android.net.TrafficStats 類來實現(xiàn)對流量統(tǒng)計的操作。
類中提供了多種靜態(tài)方法可以直接調(diào)用,返回類型均為long型;若返回-1,則代表當(dāng)前設(shè)備不支持統(tǒng)計。
部分函數(shù)如下所示:

通過文檔及上述函數(shù)可以知道,TrafficStats能夠獲取設(shè)備的數(shù)據(jù)流量和總的網(wǎng)絡(luò)流量消耗;也可以查詢uid對應(yīng)的流量信息;此外,它的使用不需要特別的權(quán)限。
其中g(shù)etUidRxBytes和getUidTxBytes實際上底層是通過讀取/proc/net/xt_qtaguid/stats后對內(nèi)容進(jìn)行解析來實現(xiàn)的。
但是它也存在一些限制:
數(shù)據(jù)在手機(jī)重啟后會清空,即所有獲得的數(shù)據(jù)都是從開機(jī)到當(dāng)前時刻的流量值:如果需要對流量進(jìn)行持續(xù)統(tǒng)計,需要將數(shù)據(jù)持久化,在手機(jī)重啟時將數(shù)據(jù)讀出并進(jìn)行累加。
無法獲取應(yīng)用的數(shù)據(jù)流量消耗:雖然API提供了獲取指定uid的流量,但無法區(qū)分不同網(wǎng)絡(luò)類型下的消耗;間接方法是通過監(jiān)聽網(wǎng)絡(luò)切換,做好流量記錄。
無法獲取某個時間段內(nèi)的流量消耗:提供的API中沒有與時間參數(shù)有關(guān)的。
NetworkStatsManager
Android 6.0開始,官方提供了NetworkStatsManager,可以獲取更具魯棒性的網(wǎng)絡(luò)歷史數(shù)據(jù)
部分函數(shù):

通過文檔及上述函數(shù)可以發(fā)現(xiàn),NetworkStatsManager相較TrafficStats而言打破了原本查詢限制,而且統(tǒng)計信息也不再是設(shè)備重啟以來的數(shù)據(jù)。
但是它仍然也存在一些限制:
使用需要額外的權(quán)限:android.permission.PACKAGE_USAGE_STATS,這個是系統(tǒng)權(quán)限,需要引導(dǎo)用戶開啟。
自帶工具
除了上面提到了兩種方式,也可以在日常開發(fā)或者使用中,利用一些自帶工具查看網(wǎng)絡(luò)流量趨勢。
手機(jī)自帶流量監(jiān)控

從Android 4.0開始,DDMS(Dalvik Debug Monitor Server)也提供了網(wǎng)絡(luò)流量使用情況的監(jiān)控。

除此之外,Android Studio等開發(fā)IDE也自帶了Network Monitor,可以在開發(fā)測試過程中輔助進(jìn)行性能問題排查。
