Android文件下载(实现断点续传)

本文将介绍在android平台下如何实现多线程下载,大家都知道,android平台使用java做为开发语言,所以java中支持的多线程下载方式在android平台下都支持,其中主要有两种方式可以实现多线程下载。 

一种方式是使用很多个线程分别下载文件的不同部分,最后把所有下载完的文件合并成一个文件。另一种方式是使用java为我们提供的RandomAccessFile类实现多线程的下载。 

从性能上分析,第二种方式的存取速度会慢一些,但开发起来较为容易,不需要进行合并文件等操作。本文将使用第二种方式来实现多线程下载,最终效果如下图所示: 

 

使用图形界面来获取需要下载的内容,并实时更新下载进度条,代码如下所示: 
Java代码   收藏代码
  1. import java.io.File;  
  2. import java.net.URL;  
  3. import java.net.URLConnection;  
  4. import android.app.Activity;  
  5. import android.os.Bundle;  
  6. import android.os.Environment;  
  7. import android.os.Handler;  
  8. import android.os.Message;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.Button;  
  12. import android.widget.EditText;  
  13. import android.widget.ProgressBar;  
  14. import android.widget.TextView;  
  15. /** 
  16.  *  Copyright (C) 2010 ideasandroid 
  17.  *  演示android多线程下载 
  18.  *  欢迎访问http://www.ideasandroid.com 
  19.  *  让程序开发不再那么神秘 
  20.  */  
  21. public class FileDownloadDemo extends Activity {  
  22.    
  23.     private EditText downloadUrl;  
  24.     private EditText downloadFileName;  
  25.     private EditText downloadThreadNum;  
  26.     private Button downloadBt;  
  27.     private ProgressBar downloadProgressBar;  
  28.     private TextView progressMessage;  
  29.     private int downloadedSize = 0;  
  30.     private int fileSize = 0;  
  31.    
  32.     @Override  
  33.     public void onCreate(Bundle savedInstanceState) {  
  34.         super.onCreate(savedInstanceState);  
  35.         setContentView(R.layout.main);  
  36.    
  37.         downloadUrl = (EditText) findViewById(R.id.downloadUrl);  
  38.         downloadFileName = (EditText) findViewById(R.id.downloadFileName);  
  39.         downloadThreadNum = (EditText) findViewById(R.id.downloadThreadNum);  
  40.         progressMessage = (TextView) findViewById(R.id.progressMessage);  
  41.         downloadBt = (Button) findViewById(R.id.downloadBt);  
  42.         downloadProgressBar = (ProgressBar) findViewById(R.id.downloadProgressBar);  
  43.         downloadProgressBar.setVisibility(View.VISIBLE);  
  44.         downloadProgressBar.setMax(100);  
  45.         downloadProgressBar.setProgress(0);  
  46.         downloadBt.setOnClickListener(new OnClickListener() {  
  47.             public void onClick(View v) {  
  48.                 download();  
  49.             }  
  50.         });  
  51.     }  
  52.    
  53.     private void download() {  
  54.         // 获取SD卡目录  
  55.         String dowloadDir = Environment.getExternalStorageDirectory()  
  56.                 + "/ideasdownload/";  
  57.         File file = new File(dowloadDir);  
  58.         //创建下载目录  
  59.         if (!file.exists()) {  
  60.             file.mkdirs();  
  61.         }  
  62.    
  63.         //读取下载线程数,如果为空,则单线程下载  
  64.         int downloadTN = Integer.valueOf("".equals(downloadThreadNum.getText()  
  65.                 .toString()) ? "1" : downloadThreadNum.getText().toString());  
  66.         //如果下载文件名为空则获取Url尾为文件名  
  67.         int fileNameStart = downloadUrl.getText().toString().lastIndexOf("/");  
  68.         String fileName = "".equals(downloadFileName.getText().toString()) ? downloadUrl  
  69.                 .getText().toString().substring(fileNameStart)  
  70.                 : downloadFileName.getText().toString();  
  71.         //开始下载前把下载按钮设置为不可用  
  72.         downloadBt.setClickable(false);  
  73.         //进度条设为0  
  74.         downloadProgressBar.setProgress(0);  
  75.         //启动文件下载线程  
  76.         new downloadTask(downloadUrl.getText().toString(), Integer  
  77.                 .valueOf(downloadTN), dowloadDir + fileName).start();  
  78.     }  
  79.    
  80.     Handler handler = new Handler() {  
  81.         @Override  
  82.         public void handleMessage(Message msg) {  
  83.             //当收到更新视图消息时,计算已完成下载百分比,同时更新进度条信息  
  84.             int progress = (Double.valueOf((downloadedSize * 1.0 / fileSize * 100))).intValue();  
  85.             if (progress == 100) {  
  86.                 downloadBt.setClickable(true);  
  87.                 progressMessage.setText("下载完成!");  
  88.             } else {  
  89.                 progressMessage.setText("当前进度:" + progress + "%");  
  90.             }  
  91.             downloadProgressBar.setProgress(progress);  
  92.         }  
  93.    
  94.     };  
  95.    
  96.     /** 
  97.      * @author ideasandroid 
  98.      * 主下载线程 
  99.      */  
  100.     public class downloadTask extends Thread {  
  101.         private int blockSize, downloadSizeMore;  
  102.         private int threadNum = 5;  
  103.         String urlStr, threadNo, fileName;  
  104.    
  105.         public downloadTask(String urlStr, int threadNum, String fileName) {  
  106.             this.urlStr = urlStr;  
  107.             this.threadNum = threadNum;  
  108.             this.fileName = fileName;  
  109.         }  
  110.    
  111.         @Override  
  112.         public void run() {  
  113.             FileDownloadThread[] fds = new FileDownloadThread[threadNum];  
  114.             try {  
  115.                 URL url = new URL(urlStr);  
  116.                 URLConnection conn = url.openConnection();  
  117.                 //获取下载文件的总大小  
  118.                 fileSize = conn.getContentLength();  
  119.                 //计算每个线程要下载的数据量  
  120.                 blockSize = fileSize / threadNum;  
  121.                 // 解决整除后百分比计算误差  
  122.                 downloadSizeMore = (fileSize % threadNum);  
  123.                 File file = new File(fileName);  
  124.                 for (int i = 0; i < threadNum; i++) {  
  125.                     //启动线程,分别下载自己需要下载的部分  
  126.                     FileDownloadThread fdt = new FileDownloadThread(url, file,  
  127.                             i * blockSize, (i + 1) * blockSize - 1);  
  128.                     fdt.setName("Thread" + i);  
  129.                     fdt.start();  
  130.                     fds[i] = fdt;  
  131.                 }  
  132.                 boolean finished = false;  
  133.                 while (!finished) {  
  134.                     // 先把整除的余数搞定  
  135.                     downloadedSize = downloadSizeMore;  
  136.                     finished = true;  
  137.                     for (int i = 0; i < fds.length; i++) {  
  138.                         downloadedSize += fds[i].getDownloadSize();  
  139.                         if (!fds[i].isFinished()) {  
  140.                             finished = false;  
  141.                         }  
  142.                     }  
  143.                     //通知handler去更新视图组件  
  144.                     handler.sendEmptyMessage(0);  
  145.                     //休息1秒后再读取下载进度  
  146.                     sleep(1000);  
  147.                 }  
  148.             } catch (Exception e) {  
  149.    
  150.             }  
  151.    
  152.         }  
  153.     }  
  154. }  

Java代码   收藏代码
  1. import java.io.BufferedInputStream;  
  2. import java.io.File;  
  3. import java.io.IOException;  
  4. import java.io.RandomAccessFile;  
  5. import java.net.URL;  
  6. import java.net.URLConnection;  
  7.    
  8. import android.util.Log;  
  9. /** 
  10.  *  Copyright (C) 2010 ideasandroid 
  11.  *  演示android多线程下载 
  12.  *  欢迎访问http://www.ideasandroid.com 
  13.  *  让程序开发不再那么神秘 
  14.  *   
  15.  *  单个下载线程 
  16.  */  
  17. public class FileDownloadThread extends Thread{  
  18.     private static final int BUFFER_SIZE=1024;  
  19.     private URL url;  
  20.     private File file;  
  21.     private int startPosition;  
  22.     private int endPosition;  
  23.     private int curPosition;  
  24.     //用于标识当前线程是否下载完成  
  25.     private boolean finished=false;  
  26.     private int downloadSize=0;  
  27.     public FileDownloadThread(URL url,File file,int startPosition,int endPosition){  
  28.         this.url=url;  
  29.         this.file=file;  
  30.         this.startPosition=startPosition;  
  31.         this.curPosition=startPosition;  
  32.         this.endPosition=endPosition;  
  33.     }  
  34.     @Override  
  35.     public void run() {  
  36.         BufferedInputStream bis = null;  
  37.         RandomAccessFile fos = null;                                                 
  38.         byte[] buf = new byte[BUFFER_SIZE];  
  39.         URLConnection con = null;  
  40.         try {  
  41.             con = url.openConnection();  
  42.             con.setAllowUserInteraction(true);  
  43.             //设置当前线程下载的起点,终点  
  44.             con.setRequestProperty("Range""bytes=" + startPosition + "-" + endPosition);  
  45.             //使用java中的RandomAccessFile 对文件进行随机读写操作  
  46.             fos = new RandomAccessFile(file, "rw");  
  47.             //设置开始写文件的位置  
  48.             fos.seek(startPosition);  
  49.             bis = new BufferedInputStream(con.getInputStream());    
  50.             //开始循环以流的形式读写文件  
  51.             while (curPosition < endPosition) {  
  52.                 int len = bis.read(buf, 0, BUFFER_SIZE);                  
  53.                 if (len == -1) {  
  54.                     break;  
  55.                 }  
  56.                 fos.write(buf, 0, len);  
  57.                 curPosition = curPosition + len;  
  58.                 if (curPosition > endPosition) {  
  59.                     downloadSize+=len - (curPosition - endPosition) + 1;  
  60.                 } else {  
  61.                     downloadSize+=len;  
  62.                 }  
  63.             }  
  64.             //下载完成设为true  
  65.             this.finished = true;  
  66.             bis.close();  
  67.             fos.close();  
  68.         } catch (IOException e) {  
  69.           Log.d(getName() +" Error:", e.getMessage());  
  70.         }  
  71.     }  
  72.    
  73.     public boolean isFinished(){  
  74.         return finished;  
  75.     }  
  76.    
  77.     public int getDownloadSize() {  
  78.         return downloadSize;  
  79.     }  
  80. }  


android多线程断点下载 
http://llb988.blog.51cto.com/1940549/510035 

Andorid多线程断点续传下载器 
http://www.jcodecraeer.com/a/opensource/2015/0602/2978.html 

Android 多线程下载 仿下载助手 
http://blog.csdn.net/u011733020/article/details/47016715 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android实现断点续传,可以使用 `DownloadManager` 类,该类提供了一个方便的方式来下载大文件,并自动支持断点续传。 以下是一个使用 `DownloadManager` 实现断点续传的示例代码: ```java DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); Uri uri = Uri.parse("http://example.com/file.zip"); DownloadManager.Request request = new DownloadManager.Request(uri); // 设置请求头,支持断点续传 long downloadedSize = getDownloadedSize(); request.addRequestHeader("Range", "bytes=" + downloadedSize + "-"); // 设置下载位置 File destinationFile = new File(getExternalFilesDir(null), "file.zip"); request.setDestinationUri(Uri.fromFile(destinationFile)); // 开始下载 long downloadId = downloadManager.enqueue(request); // 在 BroadcastReceiver 中监听下载完成事件 ``` 在上述代码中,首先获取 `DownloadManager` 的实例,并创建一个下载请求。使用 `addRequestHeader()` 方法设置请求头,以支持断点续传。然后设置下载位置,使用 `setDestinationUri()` 方法设置文件保存的位置。最后,使用 `enqueue()` 方法开始下载,并返回下载任务的 ID。可以使用 `BroadcastReceiver` 监听下载完成事件,以便在下载完成后执行其他操作。 需要注意的是,在获取已经下载的文件大小时,可以使用 `SharedPreferences` 或者其他方式来保存已经下载的大小,以便在断点续传时使用。同时,需要在 AndroidManifest.xml 文件中添加网络权限: ```xml <uses-permission android:name="android.permission.INTERNET" /> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值