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.
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
Well in app I'm trying to pull the data from sever for every 4 sec,and update the app.
I'm using handler,in that I'm calling AsynTask to fetch the data from server for every 4 sec.
Just I'm worried about the instance created for AsynTask every 4'sec causes any problem ?
This is what I'm doing.
private static final int DELAY = 1000 * 4;
final Handler printHandler = new Handler();
private boolean keepLooping = true;
printHandler.postDelayed(printStuff, DELAY);
Runnable printStuff = new Runnable(){
#Override
public void run(){
// call AsynTask to perform network operation on separate thread
new DownloadMainScore().execute("http://server/root/score.php");
if(keepLooping)
printHandler.postDelayed(this, DELAY);
}
};
On your choice of concurrency tool:
You are right that this is not so good. AsyncTasks are designed to be useful helpers when designing occasional asynchronous calls that then need to update a UI. As such, in old (< 1.6) versions of Android the maximum thread pool size was 10!
It would be better to go straight to the very robust Java out of which AsyncTask is built. Given you want to do this repeatedly, try a ScheduledExecutorService. I see they've even made a nice example for you.
Or, given that you seem to be getting a score down, best might be to maintain a persistent connection over a protocol like XMPP, for which there are many Java server and clients.
Finally, you might like to look at gcm.
On design issues in general
I see you want to print a score frequently. Once every four seconds in fact. But what's the point is the score hasn't changed? Furthermore, what if you've got a slow internet connection, and eight seconds later the one for four seconds ago hasn't finished? Right now you will set off yet another download request, even though the other one when it comes back will be up to date!
The solution is to decouple the download mechanism and the UI update mechanism. One way to do it is to have your scheduled download on a single threaded executor- not something you can control in an AsyncTask, which when finishes causes the UI to update and show the score.
Wishing you the best of luck!
Code sketch
Don't have environment set up right now, but in a very rough code sketch (check syntax), using a scheduled executor would look like:
In class:
private final ScheduledExecutorService downloadScheduler = Executors.newSingleThreadScheduledExecutor(1);
Then elsewhere, wherever you start doing this
final Runnable scoreHttpRunnable = new Runnable() {
#Override public void run() {
...
//do Http Syncronously here- I guess whatever is in the doInBackground(...) part of that Async task you wrote!
...
final int newScoreResult = ... (do whatever you do here)
...
runOnUiThread(new Runnable() { #Override public void run() { yourView.updateHoweverYouLike(newScoreResult); } })
...
};
downloadScheduler.scheduleAtFixedRate(scoreHttpRunnable, 0, 4, TimeUnit.SECONDS);
Going one of the other two routes is really too much to post in a single answer to a question. That'd be a another SO question if there isn't already one.
Be sure that next call send to asyc class only after once its done for that make a variable(IsLoadRunning) and make it true in on preExecute() and false in onPOstExecute and add a condition if(!IsLoadRunning){new DownloadMainScore().execute();}
As official documentation states
AsyncTasks should ideally be used for short operations (a few seconds at the most.)
Services can serve better in you case. Have a look at the accepted answer here
#Override
protected String doInBackground(String... params) {
Log.d(TAG, "type - " + params[0] + ", url = " + params[1] + ", name = " + params[2]);
downloadFile(params[1], params[2]);
return null;
}
here is download method
URL url = new URI(Url.replace(" ", "%20")).toURL();
URLConnection connection = url.openConnection();
connection.setConnectTimeout(1000);
int fileLength = connection.getContentLength();
mSavePath = CommonUtilities.getFileSavePath(mContext, fileName, fileLength);
Log.d(TAG, "*** saveFilePath - " + mSavePath);
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
File file = new File(mSavePath);
BufferedOutputStream bufferOutputStream = new BufferedOutputStream(new FileOutputStream(file));
byte byteArray[] = new byte[1024];
int len = 0;
long total = 0;
while ((len = inputStream.read(byteArray)) != -1) {
bufferOutputStream.write(byteArray, 0, len);
total += len;
}
bufferOutputStream.flush();
bufferOutputStream.close();
inputStream.close();
} else {
Log.d(TAG, "*** inputStream is null");
}
We usually get data from server response in android development.
/*
* get server response inputStream
*/
InputStream responseInputStream;
Solution1: get response string by multiple read.
/*
* get server response string
*/
StringBuffer responseString = new StringBuffer();
responseInputStream = new InputStreamReader(conn.getInputStream(),"UTF-8");
char[] charBuffer = new char[bufferSize];
int _postion = 0;
while ((_postion=responseInputStream.read(charBuffer)) > -1) {
responseString.append(charBuffer,0,_postion);
}
responseInputStream.close();
Solution2: get response only one read.
String responseString = null;
int content_length=1024;
// we can get content length from response header, here assign 1024 for simple.
responseInputStream = new InputStreamReader(conn.getInputStream(),"UTF-8");
char[] charBuffer = new char[content_length];
int _postion = 0;
int position = responseInputStream.read(charBuffer)
if(position>-1){
responseString = new String(charBuffer,0,position );
}
responseInputStream.close();
Which solution has better performance? why?
Notes: server response json format data that less than 1M bytes.
Why you're reinventing a wheel? ;)
If you're using HttpClient then just use EntityUtils.toString(...).
I guess you're using HttpURLConnection. Then look at EntityUtils.toString(...) from Apache HttpClient - source code. Your first approach is similar to it.
BTW, the second code is worse because:
new String(charBuffer,0,position ) runs garbage collector
In both and even in EntityUtils:
int content_length = 1024; in most cases 8192 is default for socket buffer, so your code might run while loop 8 times more often than it could.
I would recommend the second method IF you do not want to display the amount of data downloaded/transferred . As the object is read as a whole and since the size of your JSON string is comparable to 1M, it will take some time to download. At that time you can, atmost, put up a text for the user saying downloading... You cannot notify the user the amount downloaded.
But if you want to display the amount of data downloaded, use the first method that you gave. Where the you read the data from the server in parts. You can update the UI, with the amount downloaded. For eg 25 % downloaded...
char[] charBuffer = new char[bufferSize];
int _postion = 0;
int i=0;
while ((_postion=responseInputStream.read(charBuffer)) > -1) {
//((i*buffer_size)/content_length) * 100 % completed..
i++;
}
So, I would say the seconds method is better.
BTW Did you consider this?
ObjectInputStream in = new InputStreamReader(conn.getInputStream(),"UTF-8");
if(resposeCode==200)
{
String from_server=(String) in.readObject();
}
Reading the input String as an object. Any object whoe class implements serializable can be passed using ObjectOutputStream and received using ObjectInputStream()
I Think First one is good
Because, in First that will reading your response in char to char method .
Where , Second that will try to read whole response object or as key Filed of Object.
So ,As i think and as per my knowledge First is Better to camper with second.If anyone want to edit then it will truly appreciated.
I have now just started getting my feet wet in HTTP. I've been timing simple HTTP requsts using GET and POST. The web page I have used is a 3 line php check for the correct $_GET[] and $_POST[] then simply echo the character "1".
I use POST and GET with the same, single short name/value pair hoping there will be no need for packet fragmentation to muck things up, and all this is done on a thread that is off from the UI thread. The requests are looped on the phone several times while timing them. All works well. (See code below) That is, I get back the response of "1". But there is a persistent timing issue.
What I observe is that:
In the first attempt the time to make the request is much longer than the subsequent trys in both the GET and POST methods.
The rest of the attempts are always much faster for both.
GET is always faster than POST.
All these are true for 3G and Wifi connection (but with Wifi much faster overall as expected).
I have tried this with the BasicResponseHandler(), and with the more manual Buffered IO Stream methods with the same results.
I believe I understand 3. as being a result that a POST requires two transmissions, one for the 'HTTP 100' return then the packet body. - Is this correct?
My primary question is what is happening in the first request attempts that are so slow? Sometimes it takes several seconds(!). Is it the network that is holding things up or Android putting it into a socket creating queue of some sort? If it is Android, is there a way to more properly code and avoid this? Is there something about keeping a socket open to make this an issue only once during execution? If so, is it good practice to do so? Admittedly, this apsect I am most clueless about.
I have found some of discussion on this, but none hitting this aspect directly.
--
The basic code for both GET and POST methods looks like this (minus the try/catches), and are performed in a thread off the UI, first the GET method then the POST method: (output below)
GET part of it:
public String[] HTTPGETIt(int numrounds)
{
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter (CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);
HttpGet GETRequest = new HttpGet("http://mypage.com/epoch.php?mynameis=tam");
ResponseHandler <String> MyBRH = new BasicResponseHandler();
String[] GETResult = new String[numrounds];
int i = 0;
long timestart, DT;
while(i < numrounds)
{
timestart = System.currentTimeMillis();
GETResult[i] = httpclient.execute(GETRequest, MyBRH);
DT = System.currentTimeMillis() - timestart;
Log.d(TAG, "(" + i + ") GET-Round Trip was "+ DT + " ms.");
i++;
}//while i <= numrounds
httpclient.getConnectionManager().shutdown();
return GETResult;
} //END HTTPGETIt
And the POST version:
public String[] HTTPPOSTIt(int numrounds)
{
String Place = "HTTPPostping";
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);
HttpPost PostRequest = new HttpPost("http://mypage.com/epoch.php");
ResponseHandler <String> MyBRH = new BasicResponseHandler();
String[] POSTResult = new String[numrounds];
List<NameValuePair> MynameValuePairs = new ArrayList<NameValuePair>(2);
MynameValuePairs.add(new BasicNameValuePair("mynameis", "tam"));
PostRequest.setEntity(new UrlEncodedFormEntity(MynameValuePairs));
int i = 0;
long timestart, DT;
while(i < numrounds)
{
timestart = System.currentTimeMillis();
POSTResult[i] = httpclient.execute(PostRequest, MyBRH);
DT = System.currentTimeMillis() - timestart;
Log.d(TAG, "(" + i + ") POST-Round Trip was "+ DT + " ms.");
i++;
}//while i <= numrounds
httpclient.getConnectionManager().shutdown();
return POSTResult;
} // END HTTPPOSTIt
These are called by:
Runnable HTTPGETJob = new HTTPGETTask(NS);
Thread HTTPGETThread = new Thread(HTTPGETJob, "HTTPGETThread");
HTTPGETThread.setPriority(Thread.MAX_PRIORITY);
HTTPGETThread.start();
and:
Runnable HTTPPOSTJob = new HTTPPOSTTask(NS);
Thread HTTPPOSTThread = new Thread(HTTPPOSTJob, "HTTPPOSTThread");
HTTPPOSTThread.setPriority(Thread.MAX_PRIORITY);
HTTPPOSTThread.start();
With runnables:
class HTTPGETTask implements Runnable
{
int numtimes;
DeviceInfo tsrtDI;
HTTPGETTask(int inNS) {
this.numtimes = inNS;
}
#Override
public void run()
{
long [] TT2NS = new long[numtimes];
TT2NS = HTTPGETIt(numtimes);
}
};
and,
class HTTPPOSTTask implements Runnable
{
int numtimes;
DeviceInfo tsrtDI;
HTTPPOSTTask(int inNS) {
this.numtimes = inNS;
}
#Override
public void run()
{
long [] TT2NS = new long[numtimes];
TT2NS = HTTPPOSTIt(numtimes);
}
};
The output is typically:
(0) GET-Round Trip was 368 ms.
(1) GET-Round Trip was 103 ms.
(2) GET-Round Trip was 98 ms.
(3) GET-Round Trip was 106 ms.
(4) GET-Round Trip was 102 ms.
(0) POST-Round Trip was 1289 ms.
(1) POST-Round Trip was 567 ms.
(2) POST-Round Trip was 589 ms.
(3) POST-Round Trip was 496 ms.
(4) POST-Round Trip was 557 ms.
I would insist you to set the Protocol Version as HTTP 1.1 and give it a try. It would increase request/response time than what it takes now. I haven't tried it though, just got the info. So, you can try something like below before executing the request.
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
HttpVersion.HTTP_1_1);
I agree with Lalit Poptani's Answer, that may help to make faster call as it seems to be because HTTP 1.1 keeps the connection and dont do hand-shake every time.
But at the same time, I would like to say that this is not a Android specific problem, this same thing happen in almost each platform and each languages because the first time when you make any http call the platform need to create and set different objects for that assign it values to perform the call, and that stays in there, so when you make new call the time to create and assign objects is saved, so you get faster responses.
Which are these object? - that is said in above lines: I have no any pretty clear list of those but they are like proxy settings , cache memory for it.
wait few more, until someone comes with deep technical knowledge on this and explains how all stuff works in behind.
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 :)