(Android小应用)在Android中实现多线程断点下载(连载一)

当我们从Internet中下载一个文件时,有的文件比较大,比如音乐或视频文件,下载的话需要比较长的时间,当我们在下载过程中,如果手机没电了或者其它原因,使当前的下载中断了,按照一般的程序,当下次下载又需要从新开始,这里我们来实现多纯程断点下载,当下载中断了,下次启动的时候还会接着下载,有点像我们的迅雷了……

首先呢,我们先不急着建Android应用,先建一个Java项目,测试一下下

然后在这个项目里面建一个测试用例

包都可以不填,因为只是测试,不是真正的应用,偷懒了……

OK,接着写代码

  
  
package junit.test; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import org.junit.Test; public class InternetTest { /** * 读取输入流并返回数据 * @param input * @return * @throws Exception */ public byte [] readStream(InputStream input) throws Exception{ byte [] buffer = new byte [ 1024 ]; ByteArrayOutputStream output = new ByteArrayOutputStream(); int len = - 1 ; while ((len = input.read(buffer)) !=- 1 ){ output.write(buffer, 0 , len); } input.close(); output.close(); return output.toByteArray(); } /** * 从网络上下载图片 * @throws Exception */ @Test public void getImage() throws Exception{ String urlPath = " http://photocdn.sohu.com/20110401/Img280097999.jpg " ; // 在网络上随便找一张图片的链接 URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 返回一个连接对象 conn.setRequestMethod( " GET " ); // 设置请求方式 conn.setConnectTimeout( 6 * 1000 ); // 设置连接超时,这里可以不用设置,但是在android应用中应该设置超时时间 if (conn.getResponseCode() == 200 ) { InputStream input = conn.getInputStream(); byte [] data = readStream(input); File file = new File( " test.jpg " ); FileOutputStream output = new FileOutputStream(file); output.write(data); output.close(); } } /** * 得到网页html * @throws Exception */ @Test public void getHtml() throws Exception{ String urlPath = " http://www.baidu.com " ; URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod( " GET " ); conn.setConnectTimeout( 6 * 1000 ); if (conn.getResponseCode() == 200 ) { InputStream input = conn.getInputStream(); byte [] data = readStream(input); System.out.println( new String(data)); // 直接输出到控制台 } } }

然后测试,是否有预期的结果,如果有,继续下面,如果没有,再看看是不是哪儿错了

然后再建一个测试类,实现多线程下载,以下载一首mp3为例

  
  
package junit.test; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import org.junit.Test; public class DownloaderTest { /** * 读取输入流并返回数据 * @param input * @return * @throws Exception */ public byte [] readStream(InputStream input) throws Exception { ByteArrayOutputStream output = new ByteArrayOutputStream(); byte [] buffer = new byte [ 1024 ]; int len = - 1 ; while ((len = input.read(buffer)) != - 1 ) { output.write(buffer, 0 , len); } input.close(); output.close(); return output.toByteArray(); } @Test public void downloader() throws Exception { String urlPath = " http://dl.toofiles.com/vaaoje/audios/qbd.mp3 " ; URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod( " GET " ); int threadsize = 3 ; // 定义线程数 int filesize = conn.getContentLength(); // 获取文件大小 int block = filesize / threadsize + 1 ; // 每条线程下载的数量 conn.disconnect(); File file = new File( " 千百度.mp3 " ); RandomAccessFile randfile = new RandomAccessFile(file, " rw " ); // RandomAccessFile可以指定从文件的什么位置写入数据 for ( int i = 0 ;i < threadsize;i ++ ){ int startposition = i * block; // 记录每条线程的开始位置 RandomAccessFile threadfile = new RandomAccessFile(file, " rw " ); threadfile.seek(startposition); // 从文件的什么位置开始写入 new Thread( new DownloadThread(i,url,startposition,threadfile,block)).start(); } /* * 设置一个标志,当输入q的时候停止主线程 */ byte b[] = new byte [ 1 ]; System.in.read(b); while ( ! ( ' q ' == b[ 0 ])){ Thread.sleep( 3 * 1000 ); } } private class DownloadThread implements Runnable{ private int id ; private URL url; private int startposition; private RandomAccessFile threadfile; private int block; public DownloadThread( int id ,URL url, int startposition,RandomAccessFile threadfile, int block){ this .id = id; this .url = url; this .startposition = startposition; this .threadfile = threadfile; this .block = block; } @Override public void run() { // TODO Auto-generated method stub try { HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod( " GET " ); conn.setRequestProperty( " Range " , " bytes= " + startposition + " - " ); conn.setConnectTimeout( 6 * 1000 ); InputStream input = conn.getInputStream(); byte [] buffer = new byte [ 1024 ]; int len = - 1 ; int readfilesize = 0 ; // 记录下载的文件大小 while (readfilesize < block && ((len = input.read(buffer)) != - 1 )) { threadfile.write(buffer, 0 , len); readfilesize += len; // 累计下载的文件大小 } threadfile.close(); conn.disconnect(); System.out.println(( this .id + 1 ) + " 线程下载完成 " ); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }

运行此测试类,如果没有异常抛出的话就成功了……

多线程下载的核心代码已经完成,下面结合到android应用中,我们还得用到SQLite知识,要实现多线程下载,当中断的时候,我们系统会记录一个下载位置,我们把它保存在数据库中,第二次运行的时候再从数据库中读取出来,假设大家都有SQLite方面的知识……

接下来应该建Android项目了

连载中……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值