在android下面的断点续传和java下面没有太大的冲突,就是在配置文件里面加上一些特定的访问权限就可以了 如下式在AndroidManifest.xml加入的权限 <!-- 访问internet权限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 在SDCard中创建与删除文件权限--> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <!-- 往SDCard写入数据权限--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 这个准备工作做好了就可以直接编码了 第一步创建multiThreaddownload.java package com.cn.download; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.URL; import java.net.URLConnection; import com.cn.coocaa.download.FileDownloadThread; public class MultiThreadDownload extends Thread { //定义的一些常量变量,看名字就知道什么意思了 private static final int BUFFER_SIZE = 1024; private int blockSize; private int threadNum = 5; private int fileSize; private int downloadedSize; String urlStr, threadNo, fileName; private String savePath; private int downloadPercent = 0 , downloadSpeed = 0, usedTime=0; private long startTime,curTime; private boolean completed = false; //用URL,保存路径,保存名称来构造。 public MultiThreadDownload(String URL, String savePath, String fileName) { this.urlStr = URL; this.savePath = savePath; this.fileName = fileName; } @Override public void run() { FileDownloadThread[] fds = new FileDownloadThread[threadNum]; try { URL url = new URL(urlStr); URLConnection conn = url.openConnection(); fileSize = conn.getContentLength(); blockSize = fileSize / threadNum; File file[] = new File[threadNum]; //根据默认的线程数,或者自己修改设置的线程数来分块,创建分块后的文件块 for (int i = 0; i < threadNum; i++) { file[i] = new File(savePath + fileName + ".part" + String.valueOf(i)); //将分块的文件交给每个线程处理,最后一块应该大于等于平均块,因为可能有余数 FileDownloadThread fdt = new FileDownloadThread(url, file[i], i * blockSize, (i + 1) != threadNum ? ((i + 1) * blockSize - 1) : fileSize); fdt.setName("Thread" + i); fdt.start(); fds[i] = fdt; } startTime = System.currentTimeMillis(); //获取起始下载的时间,用次来计算速度。 boolean finished = false; while (!finished) { downloadedSize = 0; finished = true; for (int i = 0; i < fds.length; i++) { downloadedSize += fds[i].getDownloadSize(); if (!fds[i].isFinished()) { finished = false; } } //计算下载的百分比 downloadPercent = (downloadedSize*100)/fileSize; //获取当前时间,计算平均下载速度 curTime = System.currentTimeMillis(); usedTime =(int)((curTime-startTime)/1000); if(usedTime==0) usedTime =1; downloadSpeed = (downloadedSize/usedTime)/1024; sleep(1000); } //这个是分块下载完成的标志 completed = true; //进行模块整合 RandomAccessFile raf = new RandomAccessFile(savePath + fileName, "rw"); byte[] tempbytes = new byte[BUFFER_SIZE]; InputStream in = null; int byteread = 0; for (int i = 0; i < threadNum; i++) { in = new FileInputStream(file[i]); while ((byteread = in.read(tempbytes)) != -1) { raf.write(tempbytes, 0, byteread); } //每次整合完一块就删除一块。 in.close(); file[i].delete(); } raf.close(); } catch (Exception e) { // TODO: handle exception } } //获取下载百分比 public int getDownloadPercent(){ return this.downloadPercent; } //获取下载速度 public int getDownloadSpeed(){ return this.downloadSpeed; } //修改默认线程数 public void setThreadNum(int threadNum){ this.threadNum = threadNum; } //分块下载完成的标志 public boolean isCompleted(){ return this.completed; } } 第二步 创建filedownloadthread.java package com.cn.download; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.URL; import java.net.URLConnection; public class FileDownloadThread extends Thread { private static final int BUFFER_SIZE = 1024; private URL url; private File file; private int startPosition; private int endPosition; private int curPosition; private boolean finished = false; private int downloadSize = 0; //分块构造函数 public FileDownloadThread(URL url, File file, int startPosition, int endPosition) { this.url = url; this.file = file; this.startPosition = startPosition; this.curPosition = startPosition; this.endPosition = endPosition; } public void run() { BufferedInputStream bis = null; RandomAccessFile fos = null; byte[] buf = new byte[BUFFER_SIZE]; URLConnection con = null; try { //打开URL连接 con = url.openConnection(); con.setAllowUserInteraction(true); //判断是否该文件存在,如果存在且下载完成,直接返回。 if ((file.length() + startPosition) == endPosition) { this.finished = true; } //文件未下载完成,获取到当前指针位置,继续下载。 else { con.setRequestProperty("Range", "bytes=" + (startPosition + file.length()) + "-" + endPosition); fos = new RandomAccessFile(file, "rw"); fos.seek(file.length()); bis = new BufferedInputStream(con.getInputStream()); while (curPosition < endPosition) { int len = bis.read(buf, 0, BUFFER_SIZE); if (len == -1) { break; } fos.write(buf, 0, len); curPosition = curPosition + len; if (curPosition > endPosition) { downloadSize += len - (curPosition - endPosition) + 1; } else { downloadSize += len; } } this.finished = true; bis.close(); fos.close(); } } catch (IOException e) { System.out.println(getName() + " Error:" + e.getMessage()); } } public boolean isFinished() { return finished; } public int getDownloadSize() { return downloadSize; } } 上述两个文件就完成了多线程断点续传。 无需使用任何配置文件或者数据库,就可以接上次的断点进行续传操作。 原理流程: 1、获取文件大小 2、将文件按照所设定的线程数进行分块请求。 3、检查是否存在断点情况,如果有断点情况则进行断点查找,然后再请求。 4、分块下载。 5、下载完成后文件整合,将分块文件删除掉。 6、好了,你需要下载的文件就可以完成了。 总之了,在这里也是一种实现无需配置文件的方式吧,我提供的只是一个外部调用包,所以这个配置文件或者数据库记录的东西有很大的局限性,所以就切割了, 如果有什么更好的想法,希望能相互交流交流。 转载请注明:http://alloxa.blog.51cto.com/