簡體   English   中英

即使在 Android N 上,如何獲取應用程序的當前網絡使用情況(或總體使用情況)?

[英]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之前所需的一些步驟

  1. AndroidManifest.xml聲明所需的權限:

     <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions"/>
  2. 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 但是,這是正常權限,因此可以像任何其他權限一樣請求

  3. 使用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_MOBILEConnectivityManager.TYPE_WIFI

制作了一個示例Github 存儲庫來演示用法。

還有一種獲取統計信息的復雜方法,但這應該適用於所有適配器:(但它很昂貴,因為您必須連續讀取文件),

  1. 在這里您可以看到所有適配器和發送/接收的數據:
 cat /proc/net/dev
  1. 您可以從這些文件中獲取每個適配器的統計信息:
 cat /sys/class/net/**wlan0**/statistics/**rx**_bytes

wlan0可能是你所有的適配器,但你需要在你的應用程序中維護這個值,因為如果你關閉/打開適配器,該值將再次為 0。 (你可以有 RX 和 TX 值)

  1. 您可以獲得活動的、當前正在發送/接收的應用程序列表
cat /proc/net/**tcp6**

這也可以用tcp , tcp6 , upd , upd6來完成

這里有“uid”列,它是已安裝應用程序的 UID。 (因此該應用程序現在正在使用網絡)

從此文件中,您還可以看到連接端點。

  1. 檢查每個應用程序發送/接收的字節(如 TrafficStats API 調用)
 cat /proc/uid_stat/**10348**/tcp_snd

這里的id是應用程序 UID。 您也有 sent: tcp_snd和 received: tcp_rcv文件。

  1. 您還可以使用以下方法進行一些流程和 UID 匹配:
 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM