Question

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.

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.

No correct solution

OTHER TIPS


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

You can use the android.net.TrafficStats for getting the network usage details.

Please find a sample program below for the same.

package com.anchit.trafficstatus;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;

public class TrafficStatus extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        Log.e("bytes recvd", "" + android.net.TrafficStats.getMobileRxBytes());

        Log.e("Total", "Bytes received" + android.net.TrafficStats.getTotalRxBytes());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

The solution from Arunendra, dated 2015, didn't immediately work for me on SDK 28 (Pie).

So I modified as follows:

void networkUsage() {
    // Get running processes
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> runningApps = manager.getRunningAppProcesses();
    for (ActivityManager.RunningAppProcessInfo runningApp : runningApps) {
        long received = TrafficStats.getUidRxBytes(runningApp.uid);
        long sent = TrafficStats.getUidTxBytes(runningApp.uid);
        Log.d(LOG_TAG, String.format(Locale.getDefault(), 
                "uid: %1d - name: %s: Sent = %1d, Rcvd = %1d", runningApp.uid, runningApp.processName, sent, received));
    }
}

Note that the statistics returned by this class reset and start from zero after every reboot. To access more robust historical network statistics data, use NetworkStatsManager instead.

Src: https://developer.android.com/reference/android/net/TrafficStats

Please look at this answer for detailed info on how to use NetworkStatsManager: https://stackoverflow.com/a/39412045/6341943

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top