i'm making a soft to play online video, and i'm trying to add a traffic statistic feature tot the soft. I try to use TrafficStats and getUidRxBytes function. however, it doesnt count the videoview's net traffic.
Like the following code ,i can see the rx(return by getTotalRxBytes) increase a lot, but the myapprx(return by getUidRxBytes) doesnt change.
int uid = VideoViewPlayer.this.getApplicationInfo().uid;
long rx = TrafficStats.getTotalRxBytes();
long tx = TrafficStats.getTotalTxBytes();
long myapprx = TrafficStats.getUidRxBytes(uid);
long myapptx = TrafficStats.getUidTxBytes(uid);
String info = "uid:"+uid+" rx:"+rx+" tx:"+tx+" myrx:"+myapprx+" mytx:"+myapptx;
UPDATE
Thanks first, your comment gives me important clue. And I'm trying to find the uid responsable for steaming media. I use the following code.However i cannt find the process that comsume the traffic.
List<ActivityManager.RunningAppProcessInfo> appProcessList = am.getRunningAppProcesses();
ActivityManager.RunningAppProcessInfo info=null;
//List<ActivityManager.RunningServiceInfo> appProcessList = am.getRunningServices(100);
//ActivityManager.RunningServiceInfo info = null;
strinfo = "";
long max =0;
for(int i=0;i<appProcessList.size();++i)
{
info = appProcessList.get(i);
String key = info.processName+"_" +info.uid;
if(mNetTraffic.containsKey(key))
{
long myrx = TrafficStats.getUidRxBytes(info.uid);
long lastrx = mNetTraffic.get(key).longValue();
mNetTraffic.put(key, new Long(myrx));
if(myrx-lastrx>max && myrx - lastrx>0)
{
max = myrx-lastrx;
strinfo = key +":"+max;
}
}else
{
long myrx = TrafficStats.getUidRxBytes(info.uid);
mNetTraffic.put(key, new Long(myrx));
}
}
//trying to watch the key and max and find process and uid, sadly cant find it
Streaming media should be reported for a different UID, as it is actually streamed and played by an Android internal process and module (OpenCORE or StageFright, depending on Android version).
I had the same issue and managed to find out what UID the process has that streams media: the UID is 1013
http://forum.xda-developers.com/showthread.php?t=442557
http://android-dls.com/wiki/index.php?title=Android_UIDs_and_GIDs
Hope it helps :)
Related
i am working on an android application where i need to play find the connection's bandwidth at run time. i found out a solution on stack overflow itself saying that i can download a file from server and then by calculating size vs time , i can get the speed of connection.
Check the bandwidth rate in Android
Is this the best way (only way) to get accurate results ?
Thanks for sharing knowledge.
You can't just query for this information. Your Internet speed is determined and controlled by your ISP, not by your network interface or router.
So the only way you can get your (current) connection speed is by downloading a file from a close enough location and timing how long it takes to retrieve the file. For example:
static final String FILE_URL = "http://www.example.com/speedtest/file.bin";
static final long FILE_SIZE = 5 * 1024 * 8; // 5MB in Kilobits
long mStart, mEnd;
Context mContext;
URL mUrl = new URL(FILE_URL);
HttpURLConnection mCon = (HttpURLConnection)mUrl.openConnection();
mCon.setChunkedStreamingMode(0);
if(mCon.getResponseCode() == HttpURLConnection.HTTP_OK) {
mStart = new Date().getTime();
InputStream input = mCon.getInputStream();
File f = new File(mContext.getDir("temp", Context.MODE_PRIVATE), "file.bin");
FileOutputStream fo = new FileOutputStream(f);
int read_len = 0;
while((read_len = input.read(buffer)) > 0) {
fo.write(buffer, 0, read_len);
}
fo.close();
mEnd = new Date().getTime();
mCon.disconnect();
return FILE_SIZE / ((mEnd - mStart) / 1000);
}
This code, when sightly modified (you need mContext to be a valid context) and executed from inside an AsyncTask or a worker thread, will download a remote file and return the speed in which the file was downloaded in Kbps.
Facebook released a library for this: You can try this
https://github.com/facebook/network-connection-class
I am getting a response from server in json format and it have more then 5000 lines.
My problem is that I am not able to see complete json value in logcat and I already increase buffer size from eclipse logcat. I can not use this url in PC's web browser to check the json value because it's using some tokens to identify device. I have only one solution that I have to write a file with this json value and than extract it to my PC.
Anyone know some good solutions please help me.
You can split your lengthy response and print it like this:
int maxLogSize = 1000;
for(int i = 0; i <= veryLongString.length() / maxLogSize; i++) {
int start = i * maxLogSize;
int end = (i+1) * maxLogSize;
end = end > veryLongString.length() ? veryLongString.length() : end;
Log.v(TAG, veryLongString.substring(start, end));
}
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.
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 :
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
Have a confusion over following two methods of TrafficStats of Android:
getUidTxBytes(int uid) and getUidRxBytes(int uid) ,
These two methods return the number of bytes transmitted and received through the network for this UID. But what is the time unit of it, is it per second?
If I want to calculate data transmitted and received per day per app, what should I do. I thought one way, to store data in sql and keep on adding data to the table. Is it proper way?
These are counters "since the interface went up" or "since the application with this UID has started". So say if your phone goes into "Airplane mode" and then back, the counters might start from zero again. If you need per-second values, you'll need to call these functions every second, and then use the delta from the last call. If the delta is negative, just use the value as-is, it means the counter started from zero again.
One more thing: As far as I know, these counters count TCP/IP only. Not UDP. So if you need a very precise accounting, and the application in question uses UDP/IP, or any other protocol besides TCP, these counters will be wrong.
For the insight how this function works, look at the source of Android, freely available. File in question is ./frameworks/base/core/jni/android_net_TrafficStats.cpp
This function gets the data from /proc/uid_stat/[uid]/tcp_snd. If you need more info about that, you'll need to dive into the Linux kernel...
These counters contain the byte count since the last reboot. One some phones these counters may periodically reset, but most of the time they only reset after a reboot. Going into airplane mode or changing between mobile and Wi-Fi will not reset these counters.
One important point is that these counters do not include packet overhead, only payload size. So typically this would mean 3-4% of the data may be unaccounted for. However, if it is a streaming, torrent or VoIP app where packet payloads are small, there may be a much higher amount of data unaccounted for.
Interestingly, getTotalRxBytes (received bytes across all interfaces, ex mobile and Wi-Fi combined) and getMobileRxBytes (received bytes only on the mobile interface) include all bytes including overhead. So basically, your app byte count total will be less that your interface byte count total, and therefore less than the amount of data your network operator is billing you for.
One last point, most streaming apps don't account for their data under their own UID. They are accounted under the system.media UID. So if you are monitoring data usage for YouTube, only a very small amount of data will actually appear under that app; the rest will be under the media UID (1013).
Here, I getting those apps, which has permission of Internet,
You can change the Permission name and get apps as per you needed.
ArrayList<AppObject> listApps;
public void getAllAppList() {
listApps = new ArrayList<AppObject>();
PackageManager p = getPackageManager();
List<ApplicationInfo> packages = p.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo applicationInfo : packages) {
try {
PackageInfo packageInfo = p.getPackageInfo(applicationInfo.packageName, PackageManager.GET_PERMISSIONS);
String[] permissions = packageInfo.requestedPermissions;
for (String permissionName : permissions) {
if (permissionName.equals("android.permission.INTERNET")) {
ApplicationInfo appInfo = packageInfo.applicationInfo;
AppObject appObject = new AppObject();
appObject.appDrawable = getPackageManager().getApplicationIcon(appInfo);
appObject.appName = (String) getPackageManager().getApplicationLabel(appInfo);
appObject.dataUsage = getDataUsage(appInfo);
listApps.add(appObject);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
Debug.e("APP_SIZE", ":" + listApps.size());
appsAdapter.addAll(listApps);
}
public String getDataUsage(ApplicationInfo appInfo) {
int uid = appInfo.uid;
double received = (double) TrafficStats.getUidRxBytes(uid) / (1024 * 1024);
double sent = (double) TrafficStats.getUidTxBytes(uid) / (1024 * 1024);
double total = received + sent;
return String.format("%.2f", total) + " MB";
}
getUidRxBytes() and getUidTxBytes() are basically used for received and transmitted bytes respectively. To monitor your data for each app just find the uid of each process and find the corresponding data to each process and that will be your data for each app and then you can use this code for calculations.
TextView totData = (TextView)findViewById(R.id.totData);
TextView wifiTot = (TextView)findViewById(R.id.wifitotData);
TextView wifiTX = (TextView)findViewById(R.id.wifiUpData);
TextView wifiRX = (TextView)findViewById(R.id.wifiDownData);
TextView mobileTot = (TextView)findViewById(R.id.mobtotData);
TextView mobTX = (TextView)findViewById(R.id.mobUpData);
TextView mobRX = (TextView)findViewById(R.id.mobDownData);
/*
* Converting bytes to MB
*/
long rxBytes = TrafficStats.getTotalRxBytes()/1048576;
long txBytes = TrafficStats.getTotalTxBytes()/1048576;
long mobUpload = TrafficStats.getMobileTxBytes()/1048576;
long mobDown = TrafficStats.getMobileRxBytes()/1048576;
long wifiUpload = txBytes-(mobUpload);
long wifiDown = rxBytes-(mobDown);
wifiRX.setText(Long.toString(wifiDown));
wifiTX.setText(Long.toString(wifiUpload));
long wifitot = wifiUpload+wifiDown;
wifiTot.setText(Long.toString(wifitot));
mobTX.setText(Long.toString(mobUpload));
mobRX.setText(Long.toString(mobDown));
long mobTot = mobUpload+mobDown;
mobileTot.setText(Long.toString(mobTot));
totData.setText(Long.toString(wifitot+mobTot));
i am downloading any type of file and want to calculate Latency time that downloaded file.
Plzz help how it will be implemented in android.
Thanks
For me, something like this does the trick:
Process process = Runtime.getRuntime().exec("ping -c 1 google.com");
process.waitFor();
You can regex through the answer by reading InputStream provided by process.
I've been looking into a similar issue.
Here's some related resources that I've found.
How to test internet speed (JavaSE)?
This blog post recommends using InetAddress.getByName(host).isReachable(timeOut) and then measuring response time.
http://tech.gaeatimes.com/index.php/archive/how-to-do-icmp-ping-in-java-jdk-15-and-above/
This is likely not the best solution, but it is easy. So something like this.
String host = "172.16.0.2";
int timeOut = 3000;
long[] time = new long[5];
Boolean reachable;
for(int i=0; i<5; i++)
{
long BeforeTime = System.currentTimeMillis();
reachable = InetAddress.getByName(host).isReachable(timeOut);
long AfterTime = System.currentTimeMillis();
Long TimeDifference = AfterTime - BeforeTime;
time[i] = TimeDifference;
}
Now you have an array of 5 values that showed roughly how long it took to see if the machine is reachable by ping; false otherwise. We know if the time it difference is 3 seconds then it timed out, you could also add in an array of booleans to show success vs fail rate.
This is not perfect, but gives a rough idea of the latency at a given time.
This matches the definition of latency found at the link below, except it is measuring both the send and return time rather than the time from sender to receiver:
http://searchcio-midmarket.techtarget.com/definition/latency
Definition: In a network, latency, a synonym for delay, is an expression of how much time it takes for a packet of data to get from one designated point to another.
Doing more research shows that the isReachable might not work that great.
Android Debugging InetAddress.isReachable
This might work better.
HttpGet request = new HttpGet(Url.toString());
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
HttpClient httpClient = new DefaultHttpClient(httpParameters);
for(int i=0; i<5; i++)
{
long BeforeTime = System.currentTimeMillis();
HttpResponse response = httpClient.execute(request);
long AfterTime = System.currentTimeMillis();
Long TimeDifference = AfterTime - BeforeTime;
time[i] = TimeDifference;
}
Note: Keep in mind that this will not say the latency as you are downloading the file, but give you an idea of the latency experienced on that network at a particular period of time.
If this helps, please accept this answer.