I am facing a problem in checking of internet speed. Actually I am developing an android app which can test your internet speed on your cell phone. I make an sample to test the speed and its show write speed such as 7.3 Mbps as I am getting from my ISP. But in this test I am using below code.
long startCon = System.currentTimeMillis();
Log.i("mymobilespeedtest", "start conn = " + startCon);
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(imageURL);
HttpResponse response = null;
try {
response = httpClient.execute(httpGet);
Log.i("SketchEffect","Executing http connection to download selected image.");
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
Log.i("FBAlbum", e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
Log.i("FBAlbum", e.toString());
}
long endCon = System.currentTimeMillis();
Log.i("mymobilespeedtest", "endCon = " + endCon);
Now I want to show progress as of internet speed by using a handler and using different method download a file.'
In this method I am using below code
String downloadFileUrl = "http://www.gregbugaj.com/wp-content/uploads/2009/03/dummy.txt";
URL url1 = new URL(downloadFileUrl);
URLConnection con1 = url1.openConnection();
con1.setUseCaches(false); stream1 = con1.getInputStream();
Message msgUpdateConnection = Message.obtain(mHandler,
MSG_UPDATE_CONNECTION_TIME);
msgUpdateConnection.arg1 = (int) connectionLatency;
mHandler.sendMessage(msgUpdateConnection);
long start = System.currentTimeMillis();
int currentByte = 0;
long updateStart = System.currentTimeMillis();
long updateDelta = 0;
int bytesInThreshold = 0;
int bytesIn = 0;
while (true) {
if ((currentByte = stream1.read()) == -1) {
break;
} else {
bytesIn++;
bytesInThreshold++;
baf.append((byte) currentByte);
if (updateDelta >= UPDATE_THRESHOLD) {
int progress = (int) ((bytesIn / (double) EXPECTED_SIZE_IN_BYTES) * 100);
Message msg = Message.obtain(mHandler,
MSG_UPDATE_STATUS,
calculate(updateDelta, bytesInThreshold));
msg.arg1 = progress;
msg.arg2 = bytesIn;
mHandler.sendMessage(msg);
// Reset
updateStart = System.currentTimeMillis();
bytesInThreshold = 0;
}
updateDelta = System.currentTimeMillis() - updateStart;
}
} if (downloadTime == 0) {
downloadTime = 1;
}
Message msg = Message.obtain(mHandler, MSG_COMPLETE_STATUS,
calculate(downloadTime, bytesIn));
msg.arg1 = bytesIn;
mHandler.sendMessage(msg);
By above code I am getting only .8 or 1.o Mbps speed (In mega bit per secons not bytes)
i'm trying to do the same thing, using a HTTP GET to measure Internet Speed (download), but there is a problem. When you do this: response = httpClient.execute(httpGet); you are not measuring only the time that takes for you to receive the answer, you are measuring the time that takes to make the entire request, that means that you are measuring the overhead of the entire protocol like establishing the TCP connection between server and client.
Check this: http://tinypic.com/r/15u6og/8
The useful data that you want are the PDU's, the rest is just overhead. But you are measuring the entire thing. As you can see establishing the TCP connection takes a lot of time.
That's why you are getting a wrong value.
I know this is a little late, but have you resolved this yet?
Related
How to get 'current(actual) time' or 'network operator's time' programmatically if device time is changed ?
I'm trying to get current time through 'getLastKnownLocation' method of 'LocationManager' class. But it gives last location time, but I need current time.
Can anyone tell me a clue about the correct way to get actual time from internet ?
If possible without using any external library.
Thanks in advance.
According to this answer you can get the current time from an NTP server.
support.ntp.org library
Add to your dependency
String timeServer = "server 0.pool.ntp.org";
NTPUDPClient timeClient = new NTPUDPClient();
InetAddress inetAddress = InetAddress.getByName(timeServer);
TimeInfo timeInfo = timeClient.getTime(inetAddress);
long returnTime = timeInfo.getReturnTime();
System.out.println(returnTime)
You can use a rest full api provided by geo names http://www.geonames.org/login it will require lat and long for this purpose for example
http://api.geonames.org/timezoneJSON?lat=51.5034070&lng=-0.1275920&username=your_user_name
For Android:
Add to gradle app module:
compile 'commons-net:commons-net:3.3'
Add to your code:
...
String TAG = "YOUR_APP_TAG";
String TIME_SERVER = "0.europe.pool.ntp.org";
...
public void checkTimeServer() {
try {
NTPUDPClient timeClient = new NTPUDPClient();
InetAddress inetAddress = InetAddress.getByName(TIME_SERVER);
TimeInfo timeInfo = timeClient.getTime(inetAddress);
long setverTime = timeInfo.getMessage().getTransmitTimeStamp().getTime();
// store this somewhere and use to correct system time
long timeCorrection = System.currentTimeMillis()-setverTime;
} catch (Exception e) {
Log.v(TAG,"Time server error - "+e.getLocalizedMessage());
}
}
NOTE: timeInfo.getReturnTime() as mentioned in an earlier answer will get you local system time, if you need server time you must use timeInfo.getMessage().getTransmitTimeStamp().getTime().
Getting the time from the third-party servers is not reliable most of the times and some of them are paid services.
If you want to get the exact time and check with the phone whether it is correct or not, irrespective of the proper way, you can use the following simple trick to get the actual time.
private class GetActualTime extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
try {
HttpURLConnection urlConnection = null;
StringBuilder result = new StringBuilder();
try {
URL url = new URL(urls[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int code = urlConnection.getResponseCode();
if (code == 200) {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = bufferedReader.readLine()) != null)
result.append(line);
in.close();
}
else {
return "error on fetching";
}
return result.toString();
} catch (MalformedURLException e) {
return "malformed URL";
} catch (IOException e) {
return "io exception";
} finally {
if (urlConnection != null) {urlConnection.disconnect();
}
}
} catch (Exception e) { return "null"; }
}
#Override
protected void onPostExecute(String time) {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat mdformat = new SimpleDateFormat("h:mm");
String times = mdformat.format(calendar.getTime());
try {
String areatime = time.substring(time.indexOf(String.valueOf(times)), time.indexOf(String.valueOf(times)) + 5).trim();
Toast.makeText(this, "The actual time is " + areatime, Toast.LENGTH_SHORT).show();
}
catch(IndexOutOfBoundsException e){
Toast.makeText(this, "Mobile time is not same as Internet time", Toast.LENGTH_SHORT).show();
}
}
}
}
Call the class in the onCreate();
new GetActualTime().execute("https://www.google.com/search?q=time");
So this is actually getting the time from Google. This works pretty awesomely in my projects. In order to check whether the system time is wrong, you can use this trick. Instead of depending on the time servers, you can trust Google.
As it is more sensitive in checking, even a minute ahead or lag will catch the exception. You can customise the code if you want to handle that.
Try this :
System.currentTimeMillis();
I'm getting results from Google Search when I write a word. But I am getting less than 100 results. I want to get 500 results. How can I do this?
try {
Response response = null;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.google.com.tr/search?q="+ URLEncoder.encode(params[0],"utf-8")+"&num=500")
.build();
response = client.newCall(request).execute();
return response.body().string();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
Unfortunately, there's no way to return more than 100 results with one query. The num parameter in the URL can be anything up to 100, go over that and it'll still return 100 results.
See this guide to search URL parameters.
However, you may be able to do a workaround by using the start parameter - this will return the next 'page' of results.
For example, get the first 100:
https://www.google.ie/search?q=google+search+parameters&num=100
Then get the next 100:
https://www.google.ie/search?q=google+search+parameters&num=100&start=100
It should be easy enough to construct a loop to do this:
int num = 100;
for (int i = 0; i < 5; i++) {
String url = "http://www.google.com.tr/search?q="
+ URLEncoder.encode(params[0],"utf-8")
+ "&num=" + num
+ "&start=" + (num * i);
// Construct the request object and make the request here
}
You'll have to process each set of 100 results separately, but it should do the trick.
Hope this helps!
I'm trying to download a database from a server and then use it in my app. My initial situation is that I've got a database in my assets folder and I am trying to download the whole database from a server when the user is clicking a button.
I think I have to use the onUpgrade method but I don't know how I can download the database and then use it or and load it into the assetfolder.
You need to brake the problem into smaller issues.
Make sure that the server side is able to provide you with a web-service with which you'll do the actual download.
It would be ideal if your server would zip your sqlite database in order for you to minimize traffic.
After you have downloaded the db on your device, you'll have to unzip it, if you have taken this approach.
When you get to the point of having the db downloaded and unzipped it's just a matter of connecting to a sqlite db and Android provides api in this regards.
Of-course, all of the above needs to be done in a multithreaded environment, you could also take into account using an Android service.
This is an example of downloading a file from a server, it should help you get an idea, it's not too generic, it works in my environment.
private void handleSelectedItemDownload(final String downloadItem) {
try {
int bufferLength;
long downloadedSize = 0;
long downloadProgressBytes = 0;
final byte[] buffer = new byte[12 * 163840];
this.url = new URL(String.format(AppConstants.SERVICE_BASE_URL + AppConstants.MEDIA_IMAGE_REQUEST_URL_PATH + downloadItem));
InputStream inputStream = this.getStream(downloadedSize);
downloadedSize = this.chunkSize;
if (downloadedSize > 0) {
this.applicationFolder = downloadItem.equals("pictures") ? Utils.getThumbNailsFolder() : Utils.getApplicationFolder();
final File mediaFolder = new File(this.applicationFolder);
mediaFolder.mkdirs();
final File file = new File(mediaFolder, String.format(File.separator + downloadItem + ".zip"));
final FileOutputStream fileOutput = new FileOutputStream(file);
this.actionStatusProgressBar.setProgress(0);
final Message downloadStartMessage = new Message();
downloadStartMessage.what = ACTION_STARTED;
this.actionMessageHandler.sendMessage(downloadStartMessage);
int progressBarMax = (int) (this.totalDownloadSize / 1024);
this.actionStatusProgressBar.setMax(progressBarMax);
while (chunkSize != 0) {
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
downloadProgressBytes += bufferLength;
final Message currentProgressMessage = new Message();
currentProgressMessage.arg1 = (int) (downloadProgressBytes / 1024);
currentProgressMessage.what = ACTION_PROGRESS_VALUE;
this.actionMessageHandler.sendMessage(currentProgressMessage);
}
inputStream.close();
this.urlConnection.disconnect();
inputStream = this.getStream(downloadedSize);
downloadedSize += chunkSize;
}
fileOutput.close();
}
this.urlConnection.disconnect();
this.totalDownloadSize = 0;
} catch (MalformedURLException e) {
Log.e("DOWNLOAD_ERROR", e.getMessage() + e.toString());
this.errorEncountered = true;
this.actionType = IDataActionListener.ACTION_TYPE.ACTION_FAILED;
this.actionMessageHandler.sendEmptyMessage(ERROR_ENCOUNTERED);
} catch (IOException e) {
Log.e("DOWNLOAD_ERROR", e.getMessage() + e.toString());
this.errorEncountered = true;
this.actionType = IDataActionListener.ACTION_TYPE.ACTION_FAILED;
this.actionMessageHandler.sendEmptyMessage(ERROR_ENCOUNTERED);
} catch (Exception e) {
Log.e("DOWNLOAD_ERROR", e.getMessage() + e.toString());
this.errorEncountered = true;
this.actionType = IDataActionListener.ACTION_TYPE.ACTION_FAILED;
this.actionMessageHandler.sendEmptyMessage(ERROR_ENCOUNTERED);
}
}
private InputStream getStream(final long downloadedSize) throws IOException {
this.urlConnection = (HttpURLConnection) this.url.openConnection();
this.urlConnection.setRequestMethod("GET");
this.urlConnection.addRequestProperty("DOWNLOADED_SIZE", String.valueOf(downloadedSize));
final InputStream inputStream = this.urlConnection.getInputStream();
this.chunkSize = this.urlConnection.getContentLength();
if (!Utils.stringIsNullOrEmpty(this.urlConnection.getHeaderField("TOTAL_SIZE"))) {
if (this.totalDownloadSize == 0) {
this.totalDownloadSize = Long.parseLong(this.urlConnection.getHeaderField("TOTAL_SIZE"));
}
}
return inputStream;
}
Afterwards, when you have downloaded your db file, you can just create a SQLiteDatabase object:
final File dbFile = new File(filePath);
if (dbFile.exists()) {
this.localDatabase = SQLiteDatabase.openDatabase(filePath, null, SQLiteDatabase.OPEN_READWRITE);
this.localDatabase.setLocale(Locale.getDefault());
}
I still stick to the opinion that you should also give zipping a thought, you reduce a LOT the traffic and the time spent over network.
According to changes for kitakt 4.4 there were some problems with playing shoutcast streams (those returning "ICY" instead of "HTTP/1.x" response).
So solution for kitkat was to reregister "icy" protocol prefix in JVM once before we opened a stream by this:
try {
java.net.URL.setURLStreamHandlerFactory( new java.net.URLStreamHandlerFactory(){
public java.net.URLStreamHandler createURLStreamHandler( String protocol ) {
Log.d( LOG, "Asking for stream handler for protocol: '" + protocol + "'" );
if ("icy".equals( protocol )) return new com.spoledge.aacdecoder.IcyURLStreamHandler();
return null;
}
});
}
catch (Throwable t) {
Log.w( LOG, "Cannot set the ICY URLStreamHandler - maybe already set ? - " + t );
}
I have problem with open audio stream to make it register. After I call url.opnestream(stream) I got exception:
java.net.ProtocolException: Unexpected status line: ICY 200 OK
How could I fix it?
Here is sample of registering audio, so far what I did..
try {
URL url = null;
url = new URL(u);
inputStream = url.openStream();
startTime = System.currentTimeMillis();
Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
String fileName = File.separator + "radio_" + "recording_" + channelMetadata.replaceAll("\\W", "") + System.currentTimeMillis();
if(isSDPresent)
{
outputSource = Environment.getExternalStorageDirectory() + fileName;
}
else
{
outputSource = Environment.getDataDirectory() + fileName;
}
if(contentType.equals("audio/aacp"))
fileOutputStream = new FileOutputStream(outputSource + ".acc");
else if(contentType.equals("audio/mpeg"))
fileOutputStream = new FileOutputStream(outputSource + ".mp3");
else
fileOutputStream = new FileOutputStream(outputSource + ".nieznany_format");
int bytesRead = 0;
int bytes;
while (((bytes = inputStream.read()) != -1) && isRecording) {
fileOutputStream.write(bytes);
bytesRead++;
stopTime = System.currentTimeMillis();
long seconds = (Math.abs(startTime-stopTime));
int minutes = 1000 * 60 * 60;
if(minutes<=seconds)
{
Log.d("xxx", "recording task exceed stopped");
break;
}
}
inputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
isRecording = false;
}
isRecording = false;
return null;
Various changes were made for Android 4.4, and it seems that the non-standard ShoutCast ICY header is not supported by Android.
It seems though that the good people of OkHttp fixed the issue (issue 1 and issue 2) already a few days ago.
What you can do, is simply use OkHttp lib directly in your application and by that you'll use the newer OkHttp version (the one with the fix) and not the one shipped with Android (where you'll have to wait for an OS update).
This will also fix it for your application running on other devices that might suffer from that issue.
The answer of Assaf Gamliel worked for me. For those not familiar with this, you have to download the last .jar from okHttp and the .jar from the dependency okio . Add them to your libs directory and connect like this :
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(mediaUrl)
.build();
Response response = client.newCall(request).execute();
InputStream stream = response.body().byteStream();
The easiest fix ever.
which is 100% working for me,
for shoutcast , change your URL ex. "http://192.168.1.1:9292" to "icy://192.168.1.1:9292"
and you'll be fine.
Using: HTC Legend and HTC Salsa
I'm calculating the speed using:
while(true)
{
try
{
int num = in.read(buffer);
if(reading == false)
{
prevTime = SystemClock.uptimeMillis();
reading = true;
}
else
{
//Calculate KB/s
count += num;
Long deltaTime = SystemClock.uptimeMillis()- prevTime;
if(deltaTime >= 1000)
{
Float speed = (float)count/deltaTime;
Log.d(TAG,"Data: " + speed + "KB/s");
count = 0;
prevTime = SystemClock.uptimeMillis();
}
}
} catch (IOException e) {
}
}
And writing some test data using
out.writeUTF("ababababababababababababababababbabababaababababababababababababababababbabababaababababababababababababababababbabababa" +
"ababababababababababababababababbabababaababababababababababababababababbabababaababababababababababababababababbabababa" +
"ababababababababababababababababbabababaababababababababababababababababbabababaababababababababababababababababbabababa" +
"ababababababababababababababababbabababaababababababababababababababababbabababaababababababababababababababababbabababa");
out.flush();
The writes are within another threads while(true) also.
I'm getting the following results.
02-13 18:17:16.897: D/krazyTag(3432): Data: 31.554672KB/s
02-13 18:17:17.927: D/krazyTag(3432): Data: 29.854227KB/s
02-13 18:17:18.977: D/krazyTag(3432): Data: 29.285034KB/s
02-13 18:17:20.067: D/krazyTag(3432): Data: 38.446888KB/s
02-13 18:17:21.097: D/krazyTag(3432): Data: 35.89484KB/s
02-13 18:17:22.127: D/krazyTag(3432): Data: 33.67118KB/s
02-13 18:17:23.227: D/krazyTag(3432): Data: 33.512726KB/s
02-13 18:17:24.307: D/krazyTag(3432): Data: 33.277622KB/s
Which is confusing me since the phones specs state they use Bluetooth® 2.1 with EDR
Which is capable of 260KB/S but I'm not even getting the old standard 90KB/s
I'm not sure if it's my stream and read/write calls (I'm using a buffered datainputstream)
Or if I'm calculating things wrong or have the wrong information?
I think the speed depends on your implementation of the Send and Receive threads, since you connects 2 Android devices with your own applications. Could you post your implementation?
I got the same problem also.
I am using ACER TAB A500 to communicate with a Bluetooth stick connected to PC and I got even slower result 12,3KB/s for sending data only.
That's why I did some experiments. I sent a message for 10000times and I got that the data rate depends on the length of the message.
For 1KB message, the data rate is 232KB/s. For 40Byte message, the
data rate is 18KB/s. For 1Byte message, the data rate is
0.48KB/s.
Here is my code:
// Get the BluetoothDevice object.
while(true){
driverBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
driverBluetoothDevice = driverBluetoothAdapter.getRemoteDevice("XX:XX:XX:XX:XX:XX");
if (driverBluetoothDevice == null){
break;
}
Method insecureMethod = driverBluetoothDevice.getClass().getMethod("createInsecureRfcommSocket", new Class[] { int.class });
byte portNumber = 5; // The SPP in port 5.
driverBluetoothSocket = (BluetoothSocket) insecureMethod.invoke(driverBluetoothDevice, portNumber);
// Try to connect to the Bluetooth device.
try {
driverBluetoothSocket.connect();
} catch (IOException e1) {
// Failed to connect to the device
break;
}
// Open input and output stream.
try {
driverInputStream = driverBluetoothSocket.getInputStream();
} catch (IOException e) {
break;
}
try {
driverOutputStream = driverBluetoothSocket.getOutputStream();
} catch (IOException e) {
break;
}
byte[] message = new byte[3000];
Random randomGenerator = new Random();
for (int i = 0; i < message.length; i++){
message[i] = (byte) randomGenerator.nextInt(100);
}
Date TimeValue = new Date();
long TimeStamp1 = TimeValue.getTime();
for (int i = 0; i < 10000; i++){
try {
driverOutputStream.write(message, 0, message.length);
} catch (IOException e) {
break;
}
}
TimeValue = new Date();
long TimeStamp2 = TimeValue.getTime();
long TimeDifference = TimeStamp2 - TimeStamp1;
TimeDifference = 0;
break;
}
Not sure if this helps with your speed problem and I could have overlooked this detail in your code snippet but are you reading and writing on the same thread? The documentation suggests you don't,
First and foremost, you should use a dedicated thread for all stream reading and writing. This is important because both read(byte[]) and write(byte[]) methods are blocking calls.
Bluetooth Android Developer