Измерение скорости загрузки с помощью Java/Android

Я работаю над Android-приложением, где мне нужно как можно точнее измерить скорость загрузки текущего соединения. Вот лучший метод, который я мог найти до сих пор (в основном я запускаю таймер, начинаю загрузку дистрибутива Linux с быстрого сервера, загружаю около 200 Кбайт, затем останавливаю таймер и проверяю время, прошедшее и общее количество загруженных байтов):

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();
}   

после этого мне просто нужно разделить количество байтов, переданных на время, и это даст скорость загрузки в БПС.

вопросы: 1. Этот метод точный? 2. Вы знаете лучше?

Спасибо большое.

2 ответов


есть несколько возможных проблем:

  1. Если вы хотите сделать это на лету на произвольном устройстве (по сравнению с лабораторной настройкой), вам нужно будет следовать рекомендации Джеффри, потому что другие приложения могут потреблять пропускную способность, о которой сообщит getTotalRxBytes().

  2. это проверяет скорость загрузки с этого хоста. Если это хост, с которым вы будете общаться для "реальных вещей", это круто. Или, если вам просто в общем нужна идея скорость загрузки, все в порядке. Но тестирование скорости загрузки с сайта A и предположение, что она будет точной для сайта B, будет ненадежным, поскольку сайт A и сайт B могут даже находиться на разных континентах.

  3. Если вы ожидаете сделать это много, владелец хоста, с которым вы тестируете, может быть слегка раздражен расходом пропускной способности,чрезмерными записями журнала и т. д. В идеале, вы бы сделали это только против того, что у вас есть.

  4. для планов дозированных данных, 200KB может раздражать владельца устройства.

  5. применяются все стандартные предостережения относительно доступа в Интернет (например, сервер может быть отключен) и мобильных устройств (например, пользователь может начать работу с WiFi и выйти из диапазона, резко изменив способность загрузки).

все это, как говорится, делает загрузку является единственным реальным способом измерения скорости загрузки.


используйте код ниже. Я использовал его для измерения скорости загрузки. Вам не нужно сохранять файл для измерения скорости загрузки. Вы также, вероятно, не нужно использовать OkHttp. Я использовал его, потому что он использовался в нашем проекте.

    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);
            }
        }
    });