web-dev-qa-db-ja.com

Android Nでも)アプリの現在のネットワーク使用量(または合計)を取得するにはどうすればよいですか?

タイトルが言うように。特定のアプリが特定の時間に使用する1秒あたりのバイト数を知りたいです。

たぶん私は " netstat "コマンドを使用できますか?しかし、そうであれば、特定のアプリ/プロセスにフィルタリングするにはどうすればよいですか?

また、それを行うには何らかの許可が必要ですか?

現在、人々はTrafficStats.getUidRxBytes(packageInfo.uid)を使用すると言いますが、ここから: https://developer.Android.com/reference/Android/net/TrafficStats.html#getUidRxBytes(int) 、Nからはサポートされていないため、代わりにNetworkStatsManagerを使用する必要があると表示されます。それを使用する例はありますか?

多分マージされたソリューション?

編集:Android NでNetworkStatsManagerを使用しようとしましたが、失敗しました。使用方法のサンプルが見つかりません。また、stackOverflowに関するすべての質問は、そうでないという点で類似しています。うまく使えます。使い方を知っている人がいたら、書いてください。

16

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から、2つのメソッドを呼び出して使用量(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リポジトリ 使用法のデモ。

21
R. Zagórski

統計を取得する複雑な方法もありますが、これはすべてのアダプターで機能するはずです:(ただし、ファイルを継続的に読み取る必要があるため、コストがかかります)、

  1. ここでは、すべてのアダプターと送受信されたデータを確認できます。
cat /proc/net/dev
  1. これらのファイルからアダプタごとの統計を取得できます。
cat /sys/class/net/**wlan0**/statistics/**rx**_bytes

wlanはすべてのアダプターである可能性がありますが、アダプターをオフ/オンにすると値が再び0になるため、アプリで値を維持する必要があります。 (RXとTXの値を持つことができます)

  1. 現在送信/受信しているアクティブなアプリリストを取得できます
cat /proc/net/**tcp6**

これは、tcptcp6pdpd6でも実行できます。

ここに、インストールされているアプリのUIDである「uid」列があります。 (そのアプリは現在ネットワークを使用しています)

このファイルから、接続エンドポイントも確認できます。

  1. アプリケーションごとの送受信バイトを確認します(TrafficStats API呼び出しなど)
cat /proc/uid_stat/**10348**/tcp_snd

idここにアプリケーションUIDがあります。送信済み:tcp_sndと受信済み:tcp_rcvファイルもあります。

  1. また、次の方法でプロセスとUIDのマッチングを行うこともできます。
cat /proc/**17621**/status

ここでのIDは、たとえば、から取得できるプロセスIDです。 topコマンド。 statusファイルには、インストール済み/システムアプリのUIDであるUIDがあります。

+1。このファイルも確認できます。TrafficStatsAPIはこれを使用します。

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

したがって、最初の答えとこの知識を組み合わせると、より多くのより良い統計を得ることができます。

8
danesz

/ 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;
}
1
Arkady