3

我正在使用 AsyncTask 下载文件,目的是测量连接的下载速度。我想在 5 秒后停止下载,这样我就可以检查下载的总字节数并计算速度。这是我正在使用的代码(位于 doInBackground() 方法中):

try{                
    InputStream is = new URL("http://www.domain.com/linux.iso").openStream();
    byte[] buf = new byte[1024];

    long startTime = System.nanoTime();
    long limitTime = System.nanoTime();
    long difference = 0;    

    while (difference < 5000000000){ /*5 billion nanoseconds = 5 seconds*/
        is.read(buf);
        limitTime = System.nanoTime();
        difference = limitTime - startTime;
    }           

    is.close();
}
catch(Exception e){
    e.printStackTrace();
} 

当连接到 WiFi 时,它工作正常。测得的速度非常准确,完成测试只需 5 秒。但是,一旦我转移到 3G,测试需要 10 到 15 秒才能完成(我注意到连接越慢,完成所需的时间就越长)。

怎么会?我猜操作系统正在等待它发送的 read() 请求的回复,但不确定。

你知道无论如何都会将下载限制在 5 秒的方法吗?

提前致谢。

4

3 回答 3

2

您需要将时间计算和下载分开在不同的线程中。你是对的,因为两者都在同一个线程中,只有在完成limitTime = System.nanoTime();时才会执行is.read(buf);

于 2012-09-11T21:44:27.673 回答
1

read()绝对是阻塞调用。但我认为这是必须等待手机中的蜂窝无线电启动到全功率的结果。

确定的一种方法是打开浏览器,浏览页面,然后在页面加载后进行测试。

今年有一个非常有趣的 Google IO 演讲,讲述了蜂窝无线电如何在大部分时间处于空闲/低功耗状态,并且需要几秒钟来“预热”

我看看能不能找到视频的链接。

编辑:这是视频:

http://www.youtube.com/watch?v=PwC1OlJo5VM

电池谈话大约在 17:12 开始

http://www.youtube.com/watch?v=PwC1OlJo5VM&feature=player_detailpage#t=1032s

加速时间约为 2 秒。

演示文稿中的一张幻灯片:

在此处输入图像描述

于 2012-09-11T21:44:41.463 回答
0

试试这个代码,让我知道它是否有效:

final InputStream is = new URL("http://www.domain.com/linux.iso").openStream();
byte[] buf = new byte[1024];

final byte[] buf = new byte[1024];
long startTime = System.nanoTime();
long limitTime = System.nanoTime();
long difference = 0;

ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>()
{
    public Object call()
    {
        try
        {
            return is.read(buf);
        }
        catch(IOException e)
        {
            return null;
        }
    }
};

long endTime = 5000000000L;

while(difference < endTime)
{   
    Future<Object> future = executor.submit(task);
    limitTime = System.nanoTime();
    difference = limitTime - startTime;

    try
    {
        if(future.get(endTime - difference, TimeUnit.NANOSECONDS) == null)
        {
            System.out.println("IOException is raised on read()!");
        }
    }
    catch(TimeoutException ex)
    {
        System.out.println("TimeoutException is raised, because of the timeout!");
        break;
    }
    catch(Exception e){}
    finally
    {
        future.cancel(true);
    }
}
于 2012-09-11T22:28:17.570 回答