我正在开发一款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();
}
之后我只需要将所传输的字节数除以所需的时间,它将以bps为单位给出下载速度。
问题: 这种方法准确吗? 你知道一个更好的吗?
非常感谢。
答案 0 :(得分:4)
这里有一些可能的问题:
如果您希望在任意设备上实时执行此操作(在实验室环境中),则需要遵循Jeffrey的建议,因为其他应用程序可能会消耗{{}所报告的带宽。 1}}。
这会测试此主机的下载速度。如果这是你要与“真实的东西”进行沟通的主持人,那很酷。或者,如果您只是一般需要了解下载速度,那就没关系。但测试站点A的下载速度并假设它对站点B是准确的将是不可靠的,因为站点A和站点B可能甚至不在同一个大陆。
如果您希望这么做,您正在测试的主机的所有者可能会因带宽费用,过多的日志条目等而受到轻微的不满。理想情况下,您只会针对您拥有的内容执行此操作
对于计量数据计划,200KB可能会激怒设备所有者。
所有关于互联网访问的标准警告(例如,服务器可能已关闭)和移动设备(例如,用户可能从WiFi启动并移出范围,大幅改变您的下载能力)都适用。
所有这一切,下载是衡量下载速度的唯一真正方法。
答案 1 :(得分: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);
}
}
});
答案 2 :(得分:0)
有许多采样方法,没有一种“真实”的速度。您可以检查以下标准,以使您更好地了解推荐的方法:
https://itu.int/en/ITU-T/C-I/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个线程测试速度。不建议使用这种方式,因为它不会最大化Internet连接的全部容量。大多数标准建议使用多线程测试。
您还可以使用我们的Android SDK,该SDK应该可以满足您的要求并符合ITU标准: