Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Measuring Download Speed with Java/Android

I am working on an Android app where I need to, as accurately as possible, measure the download speed of the current connection. Here's the best method I could find so far (basically I start a timer, start downloading a Linux distro from a fast server, download around 200 kbytes, then stop the timer and check time elapsed and total bytes downloaded):

try{                
    InputStream is = new URL("http://www.domain.com/ubuntu-linux.iso").openStream();
    byte[] buf = new byte[1024];
    int n = 0;              
    startBytes = TrafficStats.getTotalRxBytes(); /*gets total bytes received so far*/
    startTime = System.nanoTime();
    while(n<200){
        is.read(buf);
        n++;                
    }
    endTime = System.nanoTime();
    endBytes = TrafficStats.getTotalRxBytes(); /*gets total bytes received so far*/
    totalTime = endTime - startTime;
    totalBytes = endBytes - startBytes;
}
catch(Exception e){
    e.printStackTrace();
}   

After that I just need to divide the number of bytes transferred by the time taken and it will give the download speed in bps.

Questions: 1. Will this method be accurate? 2. Do you know a better one?

Thanks a lot.

like image 645
Daniel Scocco Avatar asked Sep 03 '12 18:09

Daniel Scocco


People also ask

How can I check my Internet speed in Java?

Checking Internet connectivity using Java can be done using 2 methods: 1) by using getRuntime() method of java Runtime class. 2) by using methods of java URL and URLConnection classes.


2 Answers

Use the code below. I used it for measuring download speed. You don't need to save the file for the purpose of measuring download speed. You also probably don't need to use OkHttp. I used it because it was used in our project.

    String downloadURL = "http://test.talia.net/dl/1mb.pak";

    MediaType FILE = MediaType.parse("multipart/form-data;");

    OkHttpClient downloadClient = new OkHttpClient().newBuilder()
            .build();

    Request download = new Request.Builder()
            .url(downloadURL)
            .build();

    downloadClient.newCall(download).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {

        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if(response!=null) {
                long startTime = System.currentTimeMillis();
                InputStream is = response.body().byteStream();
                BufferedInputStream bis = new BufferedInputStream(is);
                long size = 0;
                int red = 0;
                byte[] buf = new byte[1024];
                while ((red = bis.read(buf)) != -1) {
                    size += red;
                }
                long endTime = System.currentTimeMillis();
                double rate = (((size / 1024) / ((endTime - startTime) / 1000)) * 8);
                rate = Math.round( rate * 100.0 ) / 100.0;
                String ratevalue;
                if(rate > 1000)
                    ratevalue = String.valueOf(rate / 1024).concat(" Mbps");
                else
                    ratevalue = String.valueOf(rate).concat(" Kbps");
                if(is!=null) {
                    is.close();
                }
                if(bis!=null) {
                    bis.close();
                }
                Log.d("download", "download speed = " + ratevalue);
            }
        }
    });
like image 45
Farhan A. Rafi Avatar answered Oct 09 '22 09:10

Farhan A. Rafi


There are a few possible problems here:

  1. If you are looking to do this on the fly on an arbitrary device (vs. in a lab setting), you will need to follow Jeffrey's recommendation, because other apps can consume bandwidth that would be reported by getTotalRxBytes().

  2. This tests download speed from this host. If that is the host you will be communicating with for "real stuff", that's cool. Or, if you just generically need an idea of download speed, it's OK. But testing download speed from Site A and assuming that it will be accurate for Site B will be unreliable, as Site A and Site B might not even be on the same continent.

  3. If you expect to do this a lot, the owner of the host you are testing against may be mildly irritated at the bandwidth expense, excessive log entries, etc. Ideally, you would only do this against something you own.

  4. For metered data plans, 200KB might irritate the device owner.

  5. All the standard caveats regarding Internet access (e.g., server may be down) and mobile devices (e.g., user might start on WiFi and move out of range, drastically changing your download ability) apply.

All that being said, doing a download is the only real way to gauge download speeds.

like image 69
CommonsWare Avatar answered Oct 09 '22 09:10

CommonsWare