[英]How to get current network usage of app (or in total), even on Android N?
正如標題所說。 我想知道特定應用程序在特定時間每秒使用多少字節。
也許我可以使用“ netstat ”命令? 但如果是這樣,我如何將其過濾到特定的應用程序/進程?
我是否還需要獲得一些許可才能這樣做?
目前人們說使用 TrafficStats.getUidRxBytes(packageInfo.uid) ,但是,從這里: https : //developer.android.com/reference/android/net/TrafficStats.html#getUidRxBytes (int ) ,它說它不受支持N ,我應該改用 NetworkStatsManager 。 有什么例子可以使用它嗎?
也許是合並的解決方案?
編輯:我嘗試在 Android N 上使用 NetworkStatsManager,但失敗了。 我找不到任何關於如何使用它的示例,並且關於它的所有 stackOverflow 問題在無法很好地使用它方面都是相似的。 請,如果有人知道如何使用它,請寫下它。
NetworkStats
的使用並不復雜。
設備 API 級別必須至少為 23。以下是開始使用NetworkStatsManager
之前所需的一些步驟
在AndroidManifest.xml
聲明所需的權限:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions"/>
在Activity
請求許可
android.permission.PACKAGE_USAGE_STATS
不是正常的權限,因此不能簡單地請求。 為了檢查權限是否已被授予,請檢查:
AppOpsManager appOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE); int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), getPackageName()); if (mode == AppOpsManager.MODE_ALLOWED) { return true; }
要請求此權限,只需調用Intent
:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS); startActivity(intent);
還需要另一個權限: Manifest.permission.READ_PHONE_STATE
。 但是,這是正常權限,因此可以像任何其他權限一樣請求
使用NetworkStatsManager
:
要獲得它的參考,請致電:
NetworkStatsManager networkStatsManager = (NetworkStatsManager) getApplicationContext().getSystemService(Context.NETWORK_STATS_SERVICE);
從NetworkStatsManager
檢索到的所有內容都打包到Buckets
。 這只是一個簡單的 POJO,用於保存數據。
全球:
要獲得WiFi的總體使用情況:
NetworkStats.Bucket bucket; try { bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, "", 0, System.currentTimeMillis()); } catch (RemoteException e) { return -1; }
從NetworkStats.Bucket
,可以調用兩種方法來獲取使用情況(以 Bps 為單位):
bucket.getRxBytes(); bucket.getTxBytes();
獲取移動網絡的數據更難。 為了獲得Bucket
調用:
public long getAllRxBytesMobile(Context context) { NetworkStats.Bucket bucket; try { bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), 0, System.currentTimeMillis()); } catch (RemoteException e) { return -1; } return bucket.getRxBytes(); } //Here Manifest.permission.READ_PHONE_STATS is needed private String getSubscriberId(Context context, int networkType) { if (ConnectivityManager.TYPE_MOBILE == networkType) { TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); return tm.getSubscriberId(); } return ""; }
應用:
要獲取特定應用程序的數據,請閱讀queryDetailsForUID的文檔。
要獲取WiFi的包使用情況:
NetworkStats networkStats = null; try { networkStats = networkStatsManager.queryDetailsForUid( ConnectivityManager.TYPE_WIFI, "", 0, System.currentTimeMillis(), packageUid); } catch (RemoteException e) { return -1; } NetworkStats.Bucket bucket = new NetworkStats.Bucket(); networkStats.getNextBucket(bucket);
要獲取Mobile的軟件包使用情況:
NetworkStats networkStats = null; try { networkStats = networkStatsManager.queryDetailsForUid( ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), 0, System.currentTimeMillis(), packageUid); } catch (RemoteException e) { return -1; } NetworkStats.Bucket bucket = new NetworkStats.Bucket(); networkStats.getNextBucket(bucket);
不幸的是,根據這段代碼獲取統計信息只能用於ConnectivityManager.TYPE_MOBILE
和ConnectivityManager.TYPE_WIFI
。
制作了一個示例Github 存儲庫來演示用法。
還有一種獲取統計信息的復雜方法,但這應該適用於所有適配器:(但它很昂貴,因為您必須連續讀取文件),
cat /proc/net/dev
cat /sys/class/net/**wlan0**/statistics/**rx**_bytes
wlan0可能是你所有的適配器,但你需要在你的應用程序中維護這個值,因為如果你關閉/打開適配器,該值將再次為 0。 (你可以有 RX 和 TX 值)
cat /proc/net/**tcp6**
這也可以用tcp , tcp6 , upd , upd6來完成
這里有“uid”列,它是已安裝應用程序的 UID。 (因此該應用程序現在正在使用網絡)
從此文件中,您還可以看到連接端點。
cat /proc/uid_stat/**10348**/tcp_snd
這里的id是應用程序 UID。 您也有 sent: tcp_snd和 received: tcp_rcv文件。
cat /proc/**17621**/status
這里的 id 是您可以從top命令獲得的進程 id。 在狀態文件中,您將擁有 UID,即已安裝/系統應用程序 UID。
+1。 你也可以看看這個文件,TrafficStats API 使用這個:
cat /proc/net/xt_qtaguid/stats
標題:
idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
價值觀:
6 eth0 0x0 10005 0 0 0 80 2 0 0 0 0 0 0 80 2 0 0 0 0
7 eth0 0x0 10005 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8 eth0 0x0 10007 0 11133 25 4751 24 11133 25 0 0 0 0 4751 24 0 0 0 0
9 eth0 0x0 10007 1 5965514 4358 102028 2327 5965514 4358 0 0 0 0 102028 2327 0 0 0 0
10 eth0 0x0 10014 0 95 1 40 1 95 1 0 0 0 0 40 1 0 0 0 0
因此,也許將第一個答案與這些知識相結合,您可以獲得更多更好的統計數據。
添加我的簡化功能以通過 /proc/net/dev 獲取整體網絡使用情況。
不需要唯一的許可。
public static long[] getNetworkUsageKb() {
BufferedReader reader;
String line;
String[] values;
long[] totalBytes = new long[2];//rx,tx
try {
reader = new BufferedReader(new FileReader("/proc/net/dev"));
while ((line = reader.readLine()) != null) {
if (line.contains("eth") || line.contains("wlan")){
values = line.trim().split("\\s+");
totalBytes[0] +=Long.parseLong(values[1]);//rx
totalBytes[1] +=Long.parseLong(values[9]);//tx
}
}
reader.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
//transfer to kb
totalBytes[0] = totalBytes[0] / 1024;
totalBytes[1] = totalBytes[1] / 1024;
return totalBytes;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.