9

我正在开发一个 Android 应用程序,我需要尽可能准确地测量当前连接的下载速度。这是迄今为止我能找到的最好的方法(基本上我启动一个计时器,开始从快速服务器下载 Linux 发行版,下载大约 200 KB,然后停止计时器并检查经过的时间和下载的总字节数):

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

之后,我只需要将传输的字节数除以所花费的时间,它就会给出以 bps 为单位的下载速度。

问题: 1. 这种方法准确吗?2.你知道更好的吗?

非常感谢。

4

3 回答 3

6

这里有几个可能的问题:

  1. 如果您希望在任意设备上即时执行此操作(而不是在实验室环境中),则需要遵循 Jeffrey 的建议,因为其他应用程序可能会消耗getTotalRxBytes().

  2. 这将测试从该主机下载的速度。如果那是您将要与“真实的东西”交流的主机,那很酷。或者,如果您通常只需要了解下载速度,那也没关系。但是测试站点 A 的下载速度并假设站点 B 的下载速度是不可靠的,因为站点 A 和站点 B 甚至可能不在同一个大陆上。

  3. 如果您希望经常这样做,您正在测试的主机的所有者可能会对带宽费用、过多的日志条目等感到轻微的恼火。理想情况下,您只会对您拥有的东西执行此操作。

  4. 对于按流量计费的数据计划,200KB 可能会激怒设备所有者。

  5. 有关 Internet 访问(例如,服务器可能已关闭)和移动设备(例如,用户可能开始使用 WiFi 并移出范围,从而极大地改变您的下载能力)的所有标准警告都适用。

话虽如此,下载是衡量下载速度的唯一真正方法。

于 2012-09-04T11:40:39.770 回答
2

使用下面的代码。我用它来测量下载速度。您不需要为了测量下载速度而保存文件。您也可能不需要使用 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);
            }
        }
    });
于 2017-03-23T12:51:19.380 回答
0

采样方法有很多种,没有一种“真正”的速度。您可以查看以下标准,让您更了解推荐的方法:

https://itu.int/en/ITU-T/CI/Pages/IM/Internet-speed.aspx

https://itu.int/itu-t/recommendations/rec.aspx?rec=q.3960

https://itu.int/ITU-T/recommendations/rec.aspx?rec=14125

https://tools.ietf.org/pdf/rfc6349.pdf

您提出的代码使用 1 个线程测试速度。不推荐这种方式,因为它不会最大化互联网连接的全部容量。大多数标准都推荐多线程测试。

您还可以使用我们的 Android SDK,它应该可以满足您的需求并符合 ITU 标准:

https://github.com/speedchecker/speedchecker-sdk-android

于 2020-11-13T12:19:09.467 回答