How to get current network usage of app (or in total), even on Android N?

后端 未结 3 1472
被撕碎了的回忆
被撕碎了的回忆 2020-12-28 08:34

As the title says. I wish to know how many bytes per second a specific app use at specific time.

Maybe I can use \"netstat\" command? But if so, how can I filter it

3条回答
  •  感情败类
    2020-12-28 08:36

    The usage of NetworkStats is not complicated.

    The device API level must be at minimum 23. Here are some steps required prior to starting the usage of NetworkStatsManager

    1. Declare the required permissions in AndroidManifest.xml:

      
      
      
    2. Ask for permission in Activity

      android.permission.PACKAGE_USAGE_STATS is not a normal permission, therefore cannot be simply requested. In order to check, whether the permission has been granted, check:

      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;
      }
      

      To ask for this permission, simply call Intent:

      Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
      startActivity(intent);
      

      Another permmission is also needed: Manifest.permission.READ_PHONE_STATE. However, this is normal permission so can be requested as any other permission

    3. Use NetworkStatsManager:

      To obtain it's reference, call:

      NetworkStatsManager networkStatsManager = (NetworkStatsManager) getApplicationContext().getSystemService(Context.NETWORK_STATS_SERVICE);
      

      Everything that is retrieved from NetworkStatsManager is packed into Buckets. This is just a simple POJO, that holds the data.

      GLOBAL:

      To get the overall usage for WiFi:

      NetworkStats.Bucket bucket;
      try {
          bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI,
                  "",
                  0,
                  System.currentTimeMillis());
      } catch (RemoteException e) {
          return -1;
      }
      

      from NetworkStats.Bucket, two methods can be called to get the usage (in Bps):

      bucket.getRxBytes();
      bucket.getTxBytes();
      

      Obtaining the data for mobile network is harder. In order to obtain the Bucket call:

      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 "";
      }
      

      APPLICATION:

      For obtaining the data for specific application, read the documentation for queryDetailsForUID.

      To get the package usage for 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);
      

      To get the package usage for 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);
      

      Unfortunately, according to this piece of code getting statistics is only possible for ConnectivityManager.TYPE_MOBILE and ConnectivityManager.TYPE_WIFI.

    Made a sample Github repo demostrating the usage.

提交回复
热议问题