android webview下载以及断点续传
2021-01-07 本文已影响0人
二八二九三十一_9178

Android部分代码
所有下载线程的信息会存储再hashmap中,但是这个是线程不安全的。不过我们只是用来存一些数据用来返回给前端进度。
/**
* 当前下载对象
* {
* key: name 线程名
* value : {
* key:filelength 文件总大小
* key:state 文件状态
* key:haveDownloaded 当前下载量
* }
* }
*/
public Map<String, Plan> planMap = new HashMap<>();
每次请求会创建一个线程进行下载,代码每次写入会有一定的性能损失,可以先缓存部分然后再一次性写入。
/**
* 下载文件
*
* @param uri 下载地址
* @throws Exception
*/
@JavascriptInterface
public void downLoad(String uri) throws Exception {
Plan verify = planMap.get(getFileName(uri));
if (verify == null || (!verify.state && verify.haveDownloaded < verify.filelength)) {
new Thread() {//子线程
public void run() {
try {
//获取服务器上文件的大小
HttpClient client = new DefaultHttpClient();
HttpHead request = new HttpHead(uri);
HttpResponse response = client.execute(request);
//response 只有响应头 没有响应体
if (response.getStatusLine().getStatusCode() == 200) {
Header[] headers = response.getHeaders("Content-Length");
String value = headers[0].getValue();
//文件大小
Long filelength = Long.parseLong(value);
Log.i("下载文件", "filelength:" + filelength);
//在sdcard创建和服务器大小一样的文件
String name = getFileName(uri);
File file = new File("/data/data/" + mContext.getPackageName() + "/files", name + ".downLoad");
if ((file.exists() && file.length() < filelength) || !file.exists()) {
//随机访问文件
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
//修改下载的开始位置 重新下载
Long start = file.length();
HttpGet httpget = new HttpGet(uri);
httpget.addHeader("Range", "bytes=" + start + "-");//添加请求头
response = client.execute(httpget);
InputStream inputStream = response.getEntity().getContent();
//跳转到起始位置
raf.seek(start);
//把流写入到文件
byte[] buffer = new byte[65536];
int len = 0;
Plan plan = planMap.get(getFileName(uri));
if (plan == null)
plan = new Plan();
plan.filelength = filelength;
plan.haveDownloaded = start;
plan.state = true;
planMap.put(name, plan);//当前线程数据更新
/*更新下载文件列表*/
updateFiles();
while ((len = inputStream.read(buffer, 0, buffer.length)) != -1 && plan.state) {
//写数据
raf.write(buffer, 0, len);
plan.haveDownloaded += len;//当前下载数
//模拟 看到进度条动的效果
// SystemClock.sleep(50);
}
httpget.releaseConnection();
inputStream.close();
//关闭
raf.close();
if (file.length() == filelength) {
file.renameTo(new File("/data/data/" + mContext.getPackageName() + "/files", name));
/*更新下载文件列表*/
updateFiles();
}
Log.i("下载", name + "下载结束");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
;
}.start();
}
}
一个用到的实体类,用来传给前端当前下载的信息
class Plan {
/**
* 总大小
*/
Long filelength;
/**
* 代表当前线程状态 true进行中 false 暂停
*/
Boolean state;
/**
* 当前已下载的数据量
*/
long haveDownloaded;
}
updateFiles这个方法是用来读取当前目录下的文件用的,有getFiles的方法给前端调用,
作用是 重启APP后获取下载记录。
代码就不贴上来了。
所有代码只提供参考思路,拒绝缝合怪