Android / Java:如何在5秒后停止下载?

我正在使用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秒内完成下载吗?

提前致谢。

read()绝对是一个阻塞调用。 但我认为这是因为必须等待手机中的手机收音机才能充满电。

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

今年有一个非常有趣的谷歌IO谈论关于小区无线电如何在大多数时间处于空闲/低功耗状态,并需要几秒钟来“热身”

我会看看能否找到video链接。

编辑:这是video:

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

电池谈话开始于17:12左右

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

它看起来像是2秒。

演示文稿中的幻灯片:

在此处输入图像描述

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

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

 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 task = new Callable() { public Object call() { try { return is.read(buf); } catch(IOException e) { return null; } } }; long endTime = 5000000000L; while(difference < endTime) { Future 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); } }