主要有两点: 网络下载位置的设置、文件写入位置的设置。
断点续传原理
在本地下载过程中要使用数据库实时存储到底存储到文件的哪个位置了,这样点击开始继续传递时,才能通过HTTP的GET请求中的setRequestProperty()方法可以告诉服务器,数据从哪里开始,到哪里结束。同时在本地的文件写入时,RandomAccessFile的seek()方法也支持在文件中的任意位置进行写入操作。同时通过广播将子线程的进度告诉Activity的ProcessBar。
---------------------
下载时新建一个下载任务,暂停时取消下载任务。
关键代码:
1、设置文件开始下载的位置
URL url = new URL(info.getUrl()); http = (HttpURLConnection)url.openConnection(); http.setConnectTimeout(10000); http.setRequestProperty("Connection", "Keep-Alive"); http.setReadTimeout(10000); http.setRequestProperty("Range", "bytes=" + mFileInfo.getDownloadLocation() + "-"); http.connect();
2、设置文件写入位置
public class DownLoadUtil { //构造方法略 public void download(){ List<FileInfo> lists = threadDAO.get(fileInfo.getUrl()); FileInfo info = null; if(lists.size() == 0){ //第一次下载,创建子线程下载 new MyThread(fileInfo).start(); }else{ //中间开始的 info = lists.get(0); new MyThread(info).start(); } } class MyThread extends Thread{ private FileInfo info = null; public MyThread(FileInfo threadInfo) { this.info = threadInfo; } @Override public void run() { //向数据库添加线程信息 if(!threadDAO.isExits(info.getUrl())){ threadDAO.insert(info); } HttpURLConnection urlConnection = null; RandomAccessFile randomFile =null; InputStream inputStream = null; try { URL url = new URL(info.getUrl()); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setConnectTimeout(3000); urlConnection.setRequestMethod("GET"); //设置下载位置 int start = info.getStart() + info.getNow(); urlConnection.setRequestProperty("Range","bytes=" + start + "-" + info.getLength()); //设置文件写入位置 File file = new File(DOWNLOAD_PATH,FILE_NAME); randomFile = new RandomAccessFile(file, "rwd"); randomFile.seek(start); //向Activity发广播 Intent intent = new Intent(ACTION_UPDATE); finished += info.getNow(); if (urlConnection.getResponseCode() == HttpStatus.SC_PARTIAL_CONTENT) { //获得文件流 inputStream = urlConnection.getInputStream(); byte[] buffer = new byte[512]; int len = -1; long time = System.currentTimeMillis(); while ((len = inputStream.read(buffer))!= -1){ //写入文件 randomFile.write(buffer,0,len); //把进度发送给Activity finished += len; //看时间间隔,时间间隔大于500ms再发 if(System.currentTimeMillis() - time >500){ time = System.currentTimeMillis(); intent.putExtra("now",finished *100 /fileInfo.getLength()); context.sendBroadcast(intent); } //判断是否是暂停状态 if(isPause){ threadDAO.update(info.getUrl(),finished); return; //结束循环 } } //删除线程信息 threadDAO.delete(info.getUrl()); } }catch (Exception e){ e.printStackTrace(); }finally {//回收工作略 } } } }