Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I programmatically show data usage of all applications?

On Android 4.0 onwards we have data usage control options in the phone. Please check the attached screen shot for further understanding.

http://developer.android.com/about/versions/android-4.0-highlights.html

Now I have some requirement to check these things (All Application's Data usage in specific time period/specific days) from my application. How can I achieve this? I am also using the below class for Network Usage details.

http://developer.oesf.biz/em/developer/reference/eggplant/android/net/NetworkStatsHistory.html

Please check the below link images. I need to develop the same kind of application.

  • http://developer.android.com/sdk/images/4.0/usage-all-lg.png

  • http://developer.android.com/sdk/images/4.0/usage-maps-lg.png

Thanks for sharing your code, but I need to know data used by each application instead of all applications. So far I observed in the links no one is talking about data usage of individual applications. I already know how to show installed applications in the device. Now I would like to know what's the data used by each and every application.

I am using the below code for list of installed applications in the device.

private ArrayList<PInfo> getInstalledApps(boolean getSysPackages) {
    ArrayList<PInfo> res = new ArrayList<PInfo>();

    List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);

    for (int i=0; i<packs.size(); i++) {
        PackageInfo p = packs.get(i);
        if ((!getSysPackages) && (p.versionName == null)) {
            continue ;
        }
        PInfo newInfo = new PInfo();
        newInfo.setAppname(p.applicationInfo.loadLabel(getPackageManager()).toString());
        newInfo.setPname(p.packageName);
        newInfo.setVersionName(p.versionName);
        newInfo.setVersionCode(p.versionCode);
        newInfo.setIcon(p.applicationInfo.loadIcon(getPackageManager()));

        res.add(newInfo);
    }
    return res;
}

How do I know what's the data used by each application?

Actually, I need a solution which gives data usage of applications in a given time period, i.e. in between two days.

like image 291
Kiran_b Avatar asked Jul 16 '13 11:07

Kiran_b


People also ask

How do you keep track of data usage?

Select “Network & Internet” from the top of the “Settings” menu. Tap “Mobile Network.” At the top of the screen, you'll see how much data you have used this month. To see which apps are using the most data, tap “App Data Usage.”


1 Answers


Old Answer (Mostly work for devices below Api level 23)

First, get a list of all running apps' process info:

List<RunningAppProcessInfo>

Then get the UID of every app and get then send and receive traffic of the app:

// Get running processes
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningApps = manager.getRunningAppProcesses();

for (RunningAppProcessInfo runningApp : runningApps) {

  // Get UID of the selected process
  int uid = ((RunningAppProcessInfo)getListAdapter().getItem(position)).uid;

  // Get traffic data
  long received = TrafficStats.getUidRxBytes(uid);
  long send   = TrafficStats.getUidTxBytes(uid);
  Log.v("" + uid , "Send :" + send + ", Received :" + received);
}

Edited Answer

There are some more options to get network usage :

  1. NetworkStatsManager - So NetworkStatsManager is an option which is also provides required info but it has a drawback i.e. This API is available only on Marshmallow(API level 23) or higher. For the devices below to api 23 the my old answer can be used.
According to the official documentation:


[NetworkStatsManager] provides network traffic statistics. These statistics include bytes transmitted and received and network packets transmitted and received, over all interfaces, over the mobile interface, and on a per-UID basis.

So to use NetworkStatsManager :

  • Declare required permissions in AndroidManifest file :

    <uses-permission android:name="android.permission.READ_PHONE_STATE" / >
    
    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
     tools:ignore="ProtectedPermissions" / >
    

Since “android.permission.PACKAGE_USAGE_STATS” is a system level permission we will need to handle the request in a different manner. 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;
}

This permission can be granted from the Settings -> Security -> Apps with usage access screen. To ask for this permission, simply start an activity with Settings.ACTION_USAGE_ACCESS_SETTINGS Intent to help the user to get there:


startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));

Once everything has been set up you can get an instance of NetworkStatsManager which we will need to fetch network usage data:

NetworkStatsManager networkStatsManager = (NetworkStatsManager) context.getSystemService(Context.NETWORK_STATS_SERVICE);
  • Whatever query you will perform, you will get as a result a NetworkStats.Bucket or a NetworkStats (which is basically a container for multiple buckets with methods hasNextBucket() and getNextBucket() to access the real data (also remember to use close() before the object is out of scope).

  • In every query you will have to specify the network type (ConnectivityManager.TYPE_WIFI or ConnectivityManager.TYPE_MOBILE). 


  • Subscriber Id required to make query and it remains same unless the user switches SIM card or carrier. To get that

TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 

String subscriberId = manager.getSubscriberId();
  • To access an individual app stats you will need the uid of that app, which is an int value assigned by the system to each app at install time.
PackageManager packageManager = context.getPackageManager();

ApplicationInfo info = packageManager.getApplicationInfo("com.example.app", 0); 

int uid = info.uid;

UIDs used for the network usage caused by : 


  • Unistalled apps : UID_REMOVED

  • Tethering : UID_TETHERING
  • Android OS : SYSTEM_UID 

  • To get stats for all apps : UID_ALL

Some example queries:

To get all Rx and Tx bytes of Mobile :

NetworkStats.Bucket bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), 0, System.currentTimeMillis());
        
    
bucket.getRxBytes();
bucket.getTxBytes();
        

To get all Rx and Tx bytes of Wifi :

NetworkStats.Bucket bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, ””, 0, System.currentTimeMillis());
       
bucket.getRxBytes();
bucket.getTxBytes();

To get all Rx and Tx bytes of Mobile for package :

NetworkStats.Bucket bucket = networkStatsManager.queryDetailsForUid(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), 0, System.currentTimeMillis(),packageUid);
            
            
    
long rxBytes = 0L;
           
long txBytes = 0L;
            
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
           
while (networkStats.hasNextBucket()) {
            
     networkStats.getNextBucket(bucket);
     rxBytes += bucket.getRxBytes();
     txBytes += bucket.getTxBytes(); 
}
networkStats.close();

To get all Rx and Tx bytes of Wifi for package :

NetworkStats.Bucket bucket = networkStatsManager.queryDetailsForUid(ConnectivityManager.TYPE_WIFI, “”, 0, System.currentTimeMillis(),packageUid);
        

long rxBytes = 0L;
           
long txBytes = 0L;
            
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
           
while (networkStats.hasNextBucket()) {
            
     networkStats.getNextBucket(bucket);
     rxBytes += bucket.getRxBytes();
     txBytes += bucket.getTxBytes(); 
}
networkStats.close();

Note :

  • Those queries should never be performed on the main thread or they will cause your app to drop frame.
  • NetworkStatsManager.query* throws RemoteException
  • Roaming and tag were added in API level 24 (Android 7.0 Nougat) so if you’re targeting Marshmallow (API level 23) you won’t be able to use those.
  • Since API level 24 (Android 7.0 Nougat) you can use NetworkStatsManager without the PACKAGE_USAGE_STATS permission if you only want to get your app data. You’d still need it if your goal is to access other apps’ stats.

2. TrafficStats : It also provides required info but there are some drawbacks which makes it unreliable at least :


  • Data resets after every reboot 

  • It may also be unsupported on some devices.

Some example methods of TrafficStats:

- To get Total Rx bytes          -  TrafficStats.getTotalRxBytes();
   
- To get Total Tx bytes          -  TrafficStats.getTotalTxBytes();
    
- To get all Mobile Rx bytes     -  TrafficStats.getMobileRxBytes();
        
- To get all Mobile Tx bytes     -  TrafficStats.getMobileTxBytes();
        
- To get all Wifi Rx bytes       -  TrafficStats.getTotalRxBytes() - TrafficStats.getMobileRxBytes();
    
- To get all Wifi Tx bytes       -  TrafficStats.getTotalTxBytes() - TrafficStats.getMobileTxBytes();
- To get Package Rx Bytes :      -  TrafficStats.getUidRxBytes(packageUid);
- To get Package Tx Bytes :      -  TrafficStats.getUidTxBytes(packageUid);
like image 126
Arunendra Avatar answered Sep 20 '22 11:09

Arunendra