Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
215 views
in Technique[技术] by (71.8m points)

android - 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.

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...