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
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
Declare the required permissions in AndroidManifest.xml
:
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
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.