Question

(I think this is a common question but please don't mark as duplicate too quickly as I believe my answers add something new to the discussion.)

The relevant API is TrafficStats, which gets its data from e.g. /proc/uid_stat/.

The stats must include GCM etc., not just stuff I initiate, so the thread and tag based counters are not sufficient.

The first problem is an API to get mobile data usage based on UID (i.e. per app) is conspicuously absent. There are getMobile API's and getUid API's, but nothing that combines them. I propose a solution to this as one answer below.

More importantly, I'm getting the impression that TrafficStats has too many bugs to be usable for this general purpose. I put that as a possible answer too, and if that is accepted then the best solution is to count data usage manually.

Was it helpful?

Solution 2

I think the best solution is to use something like wireshark to measure the data used by the various network operations of your app, and then track your data consumption manually. Which is certainly do-able.

I say that because the bugs in TrafficStats are accumulating faster then they are being fixed, and patches are being ignored, so I have the impression that TrafficStats isn't being maintained and should be avoided. JBQ assigned many before he quit, but I believe he was just cleaning up. I realize that Android settings includes data usage stats. I have not investigated but would guess that those are also not reliable (sorry that I'm being lazy but I've already concluded that I would have wasted much less time if I just did my calculations manually).

Here are some of the bugs in trafficstats that I came across (some of the issues are in TraffficStats, some originate in the kernel) while looking at general API's. I have not tried the thread/tag/socket based API's, and don't plan to based on my experience so far, but would be interested to hear if they work better.

In 2.x
Android TrafficStats.getTotalRxBytes() is less than expected

In 3.x
TrafficStats.getMobileRxBytes() and TrafficStats.getMobileTxBytes():
https://code.google.com/p/android/issues/detail?id=19938
TrafficStats APIs do not report UDP traffic even though API level 12 onwards they should have been supported (never fixed):
https://code.google.com/p/android/issues/detail?id=32410

In 4.3, the getUid API's are totally broken, but it sounds like they might be planning to fix this bug. Regardless, if the bug has gone out to Google's partners then I think these API's are useless for the forseeable future.

TrafficStats.getUidRxBytes and getUidTxBytes always return 0 in 4.3:
https://code.google.com/p/android/issues/detail?id=58210
And see this SO post.

OTHER TIPS

Here is my initial solution. The API's are actually broken in multiple ways, both old and new, so this is just a solution that could be used if they are fixed.

Getting stats for your app is simple:

int uid = android.os.Process.myUid();
txBytesInitial = TrafficStats.getUidTxBytes(uid);
rxBytesInitial = TrafficStats.getUidRxBytes(uid);

So, every time a network connection is lost (or app closes, or stats are needed by app logic) the delta in your app's data usage is added to your stats, based on NetworkInfo.getType(). You would need to maintain the last retrieved for use in the delta calculation and these would need to be stored in e.g. SharedPreferences and reset when the phone reboots or whenever they go in the wrong direction (depending on the device they can be reset for reasons other then restart).

See this useful SO post with some additional explanation about these API's (e.g. they don't include packet overhead, just payload).

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