android多线程断点下载

用一种持久化存储的方式保存每个线程下载的进度, 每次下载开始的时候, 检查是否有保存未完成的进度
如果有未完成的, 从上次记录的位置继续
public class BreakPointDownService {
private String source;
private Handler handler;
private URL url;
private String filename;// 文件名
private long threadlength;// 每条现成下载的总长度
private final static int AMOUNT = 3;// 分三条现成下载
private long currentlength; // 当前总共完成了多少


private File file;
private File localfile;//本地文件
private File localtemp;//临时记录的文件,记录文件下载进度的文件(跟下载文件最好在同一个路径)
private long totallength;


public BreakPointDownService(String source, Handler handler)
throws Exception {
this.source = source;
this.handler = handler;
filename = source.substring(source.lastIndexOf("/") + 1);
System.out.println("filename" + filename);
url = new URL(source);
localfile = new File("/mnt/sdcard/" + filename);
localtemp = new File(localfile.getAbsolutePath()+".temp");//临时文件


}


// 用randomaccess来实现多线程下载
// 首先定义一个下载方法,然后开启多个线程来实现下载
public void download() throws Exception {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(3000);
totallength = conn.getContentLength();
System.out.println(totallength);


Message msg = new Message();
msg.what = 1;// 设置标识码
msg.getData().putLong("totallength", totallength);
handler.sendMessage(msg);// 把最大数据发送到主线程中


if (!localfile.exists()) {
RandomAccessFile raf = new RandomAccessFile(localfile, "rws");// 创建本地文件
// 设置文件的大小
raf.setLength(totallength);
raf.close();
}
if (!localtemp.exists()) {
RandomAccessFile raf = new RandomAccessFile(localtemp, "rws");//因为有三个线程下载文件,那么就应该三个long的变量记录下载进度
for(int x= 0;x<AMOUNT;x++){
//按照线程数来记录下载进度
raf.writeLong(0);//写入一个long型的数据,每一个long可以记录当前文件的下载进度
}
raf.close();
}
threadlength = (totallength + AMOUNT - 1) / AMOUNT;// 设置每一个现成下载的大小
RandomAccessFile raf = new RandomAccessFile(localfile, "rws");// 每读取一个字节,就会存储一个字节rws模式
raf.setLength(totallength);// 设置文件的大小
raf.close();
// 开启数个现成,来实现下载
for (int i = 0; i < AMOUNT; i++) {
// 开启线程下载
new ThreadDown(i).start();
}
}
private class ThreadDown extends Thread {
private int x;


ThreadDown(int x) {
this.x = x;
}


// 开启一个线程下载
public void run() {
long start = x * threadlength; // 一个现成下载的开始位置 即randomaccess流开始写入的位置
long end = x * threadlength + threadlength - 1;// 一个线程下载结束的位置即randomaccess流关闭的位置,如果文件写完了,则自动关闭
HttpURLConnection conn;
try {
//首先打开零时文件,读取下载进度(本地)
RandomAccessFile tempraf = new RandomAccessFile(localtemp, "rws");
tempraf.seek(x*8);//每个线程写8个字节,这样每个线程移动到需要读取的下载的进度(每个线程写1个long值, 占8字节)
long threadfinish = tempraf.readLong();//读取下载的进度(读取一个long的数字)
synchronized (BreakPointDownService.class) {//由于是同一个文件
currentlength+=threadfinish;//统计线程总共下载了多少,由于有多个线程操作,所以需要同步()
}
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(3000);


**conn.setRequestProperty("Range", "bytes=" + start + "-" + end); // 在请求头中设置当前线程下载的范围


// 获取输入流,开始写文件


InputStream in = conn.getInputStream();
RandomAccessFile localraf = new RandomAccessFile(localfile, "rws");//装载本地数据(可以理解为输出流)
localraf.seek(start);// 设置文件开始的位置
int len;
byte[] buf = new byte[1024 * 100];// 每次读取100k
while ((len = in.read(buf)) != -1) {
//每一次写入记录文件写入的大小

synchronized (BreakPointDownService.this) { // 多个下载线程之间同步,下载总长度同一时间只能有一个线程修改
currentlength += len; // 统计所有线程总共完成了多少
// 发送当前进度--------------
Message msg = new Message();
msg.getData().putLong("currentlength", currentlength);
msg.what = 2;
handler.sendMessage(msg);
}
localraf.write(buf, 0, len);// 写到本地
threadfinish+=len;//记录某一个线程所下载的大小
//让然后写本地记录文件之中
tempraf.seek(x*8);//到指定位置
tempraf.writeLong(threadfinish);//记录当前线程所下载的大小
}
localraf.close();
tempraf.close();
// 不能关闭输入流,文件未写完

if(currentlength==totallength){
localtemp.delete();//如果文件已经下载完毕,则删除零时记录文件.
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值