9

I feel like I am on crazy pills right now. A specific part of my application has been working just fine for several days, and today it just stopped working and I can not figure out why. This part of my code used to output the total data since boot that each specific app has sent and received. Now, the values always show up as 0.

A couple things that may or may not be affecting this:

1.) My Nexus 4 was just updated to Android 4.3 today, but I doubt this is an issue because this worked just fine right after I updated.

2.) With the Android API 18 update, some methods from the Traffic Stats API are now deprecated, but these are methods I am not even using, so this should have no effect. http://developer.android.com/reference/android/net/TrafficStats.html

All help is greatly appreciated.

PackageManager packageManager=this.getPackageManager();
List<ApplicationInfo> appList=packageManager.getInstalledApplications(0);

for (ApplicationInfo appInfo : appList) {
    String appLabel = (String) packageManager.getApplicationLabel(appInfo);
    int uid = appInfo.uid;
    Log.d("data", String.valueOf(TrafficStats.getUidRxBytes(uid) + TrafficStats.getUidTxBytes(uid)));

Update[January 23, 2014]: Testing the getUidRxBytes() and getUidTxBytes() on my Nexus 4 running Android 4.4.2 shows that the values are no longer 0, but are reporting the correct statistics.

Dick Lucas
  • 12,289
  • 14
  • 49
  • 76
  • Despite your objections, I think the two things you mentioned are probably the most likely causes. – Robert Harvey Jul 27 '13 at 06:33
  • I appreciate the response Robert, but like I said, I don't think these could be the issues, because everything worked after I updated to 4.3. It was a few hours later when it started reporting 0 for some reason. – Dick Lucas Jul 27 '13 at 06:40
  • gonna flash the nexus back to 4.2 to see if that works, brb – Dick Lucas Jul 27 '13 at 19:19
  • 1
    Aaahh hell no. The above code works perfectly when run on Android 4.2.2. But on Android 4.3, it reports all the apps as having transferred 0 bytes since boot. This is disconcerting, considering none of the methods used in the above code have been deprecated and there is no indication here: http://developer.android.com/reference/android/net/TrafficStats.html or anywhere else that any of the methods used should be working any differnetly in 4.3. – Dick Lucas Jul 27 '13 at 21:55
  • Update: I have reported this on the AOSP issue tracker. I will update as I learn more: https://code.google.com/p/android/issues/detail?id=58210&q=label%3AReportedBy-Developer&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars – Dick Lucas Jul 30 '13 at 04:03

3 Answers3

6

I have reported the issue to the AOSP issue tracker: here

I have also created an alternate solution to the problem which I have pasted below:

private Long getTotalBytesManual(int localUid){

File dir = new File("/proc/uid_stat/");
String[] children = dir.list();
if(!Arrays.asList(children).contains(String.valueOf(localUid))){
    return 0L;
}
File uidFileDir = new File("/proc/uid_stat/"+String.valueOf(localUid));
File uidActualFileReceived = new File(uidFileDir,"tcp_rcv");
File uidActualFileSent = new File(uidFileDir,"tcp_snd");

 String textReceived = "0";
 String textSent = "0";

 try {
        BufferedReader brReceived = new BufferedReader(new FileReader(uidActualFileReceived));
        BufferedReader brSent = new BufferedReader(new FileReader(uidActualFileSent));
        String receivedLine;
        String sentLine;

        if ((receivedLine = brReceived.readLine()) != null) {
            textReceived = receivedLine;
        }
        if ((sentLine = brSent.readLine()) != null) {
            textSent = sentLine;
        }

    }
    catch (IOException e) {

    }
 return Long.valueOf(textReceived).longValue() + Long.valueOf(textReceived).longValue();

}
Dick Lucas
  • 12,289
  • 14
  • 49
  • 76
  • You've written "textReceived" twice at the last line of code. Also you didn't close the readers, and used "String.valueOf" (and twice) instead of calling "Long.toString" . I also have a question about this: the official documentation says it gets the data since last boot, but it seems this method takes the whole number, eevn before the current session of the OS. How could it be? – android developer May 30 '14 at 23:44
  • **I checked the issue status and tested your code**, it seems for security reasons they don't want anyone to know which app is using internet, hence the `uid_stat` directory is empty, and even your code failed to work (or maybe needs the device to be **root**ed). – Top-Master Oct 13 '20 at 12:35
3

The TrafficStats class get the information about network traffic from the /proc/uid_stat/<uid> directory. This contains information about the tcp, udp bytes and packets sent and received. If the files are not present the TrafficStats class can't get the network stats. You can check if the files are present, If not you are out of luck and should look for other way.

If the files are present you can try to read it yourself.

Also the getUidTxBytes() and getUIDRxBytes() report only the TCP traffic and miss UDP traffic. So if your app is doing lots of UDP traffic (like voip) then you'll not get any info. There is already a bug filed for this : https://code.google.com/p/android/issues/detail?id=32410

Srikant Sahay
  • 885
  • 6
  • 9
  • The files do exist in the directory you specified. Each uid has a folder named after itself, e.g. 10033. Within each folder there are two text files, one called "tcp_rcv" and another "tcp_snd", each containing a number in them. And these numbers are not 0, so getUidRxBytes() and getUidTxBytes() should be returning proper values. Thank you for your help. – Dick Lucas Jul 31 '13 at 22:56
  • Does any one about fixes for 6.0.x ? Or alternative methods? thanks – martin Mar 16 '17 at 20:25
2

I have done some detailed research about this, and to clarify some details, since Android 4.3 the TrafficStats API has changed in the way it extracts details from the device.

Prior to Android 4.3 the UID traffic stats were available for TCP and UDP and included API for bytes and packets & sent and received. That data was extracted from the /proc/uid_stat/[pid]/* files.

In Android 4.3, the developers has decided to switch to a better and more safe API, using the xt_qtaguid UID statistics, which is part of the netfilter kernel module in Linux. This API (procfs) allows access based on process UID, and this is why when you try to access to TrafficStats API in Android=>4.3 you will get zero information for not-own UID.

btw, the commit that caused the issue is the following: https://github.com/android/platform_frameworks_base/commit/92be93a94edafb5906e8bc48e6fee9dd07f5049e

*Improve TrafficStats UID APIs. Deprecate transport layer statistics, leaving only the summarized network layer statistics. Improve documentation to be clear about layers where measurements occur, and their behavior since boot. Under the hood, move to using xt_qtaguid UID statistics. Bug: 6818637, 7013662 Change-Id: I9f26992e5fcdebd88c671e5765bd91229e7b0016*

Roman Blachman
  • 227
  • 6
  • 13
  • So the official framework return 0 for all applications except the current one? why is it considered safer ? they are just statistical numbers, and they are even available via the settings of the OS. Also, will reading from the "/proc/uid_stat" still work and return the correct results? Some people claim the whole thing got fixed on Android 4.4, but I don't see that it got fixed (returns 0 for all apps). – android developer May 31 '14 at 08:06