本文为大家分享了实现断点续传下载的具体代码,供大家参考,具体内容如下
1、基于Ok+Rxjava实现断点续传下载
2、基于Ok+Rxjava+Retrofit实现断点续传下载
最近总结一下了一下之前学过以及用到过得功能,整理了一个基于Ok+Rxjava实现断点续传下载的demo。下面先给大家展示一下使用效果吧。
说下我的大致思路吧:根据文件下载url按照自己定义的规则生成文件名,判断本地同路径下是否存在此文件,如果存在,文件大小与服务器上获取的文件大小一致的情况下,则生成新的文件名重新下载;如果文件比服务器获取的文件大小小,则执行断点下载,从本地文件长度处开始下载。如果文件不存在,则从0字节开始下载。
DownloadSubscribe(被观察者)中执行下载存入本地操作
核心还是:addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength)
DownLoadObserver(观察者)通过onnext(DownloadInfo downloadInfo)方法回调下载进度
下面上主要代码:
public void download(final String url, final DownFileCallback downFileCallback) {
if (url == null || downCalls.get(url) != null) {
return;
}
Observable.just(url)
.filter(new Predicate() {
@Override
public boolean test(String s) throws Exception {
//过滤条件 若map中存在,则这次不下载
return !downCalls.containsKey(s);
}
})
.flatMap(new Function>() {
@Override
public ObservableSource apply(String s) throws Exception {
//创建下载实体类
return Observable.just(createDownInfo(s));
}
})
.map(new Function() {
@Override
public DownloadInfo apply(DownloadInfo s) throws Exception {
//根据本地是否存在此文件,来设置文件名及文件初始下载大小
return getRealFileName(s);
}
})
.flatMap(new Function>() {
@Override
public ObservableSource apply(DownloadInfo downloadInfo) throws Exception {
//创建被观察者
return Observable.create(new DownloadSubscribe(downloadInfo));
}
})//下载
.observeOn(AndroidSchedulers.mainThread())//在主线程回调
.subscribeOn(Schedulers.io())//在子线程执行
.subscribe(new DownLoadObserver() {//添加观察者
@Override
public void onNext(DownloadInfo downloadInfo) {
super.onNext(downloadInfo);
downFileCallback.onProgress(downloadInfo.getTotal(), downloadInfo.getProgress());
}
@Override
public void onError(Throwable e) {
super.onError(e);
if (!(e instanceof SocketException)) {
downFileCallback.onFail(e.getMessage());
}
}
@Override
public void onComplete() {
downFileCallback.onSuccess(url);
}
});
}
public void cancel(String url) {
Call call = downCalls.get(url);
if (call != null) {
call.cancel();//取消
}
downCalls.remove(url);
}
private class DownloadSubscribe implements ObservableOnSubscribe{ private DownloadInfo downloadInfo; public DownloadSubscribe(DownloadInfo downloadInfo) { this.downloadInfo = downloadInfo; } @Override public void subscribe(ObservableEmitter e) throws Exception { String url = downloadInfo.getUrl(); long downloadLength = downloadInfo.getProgress();//已经下载好的长度 long contentLength = downloadInfo.getTotal();//文件的总长度 //初始进度信息 e.onNext(downloadInfo); Request request = new Request.Builder() //断点续传的核心 .addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength) .url(url) .build(); Call call = mClient.newCall(request); //根据下载url,把call存放在map中,取消的时候就可以通过call.cancle()来实现 downCalls.put(url, call); Response response = call.execute(); File file = new File(getTemporaryPath(), downloadInfo.getFileName()); InputStream is = null; FileOutputStream fileOutputStream = null; try { is = response.body().byteStream(); fileOutputStream = new FileOutputStream(file, true); byte[] buffer = new byte[2048];//缓冲数组2kB int len; while ((len = is.read(buffer)) != -1) { fileOutputStream.write(buffer, 0, len); downloadLength += len; downloadInfo.setProgress(downloadLength); e.onNext(downloadInfo); } fileOutputStream.flush(); downCalls.remove(url); } finally { //关闭IO流 IOUtil.closeAll(is, fileOutputStream); } e.onComplete();//完成 } }
private long getContentLength(String downloadUrl) {
Request request = new Request.Builder()
.url(downloadUrl)
.build();
try {
Response response = mClient.newCall(request).execute();
if (response != null && response.isSuccessful()) {
long contentLength = response.body().contentLength();
response.close();
return contentLength == 0 ? DownloadInfo.TOTAL_ERROR : contentLength;
}
} catch (IOException e) {
e.printStackTrace();
}
return DownloadInfo.TOTAL_ERROR;
}
从服务器获取文件长度的时候注意一下,Android P之后,也就是api 28以上禁止明文网络传输。需要在你的AndroidManifest中的application标签中声明"android:usesCleartextTraffic="true",允许应用进行明文传输。
使用方法:首先要获取sd卡权限
DownloadManager.getInstance().downloadPath(本地存在地址).download(url1, new DownFileCallback() {
@Override
public void onProgress(long totalSize, long downSize) {
progress1.setMax((int) totalSize);
progress1.setProgress((int) downSize);
}
@Override
public void onSuccess(String url) {
Toast.makeText(MainActivity.this, url1 + "下载完成", Toast.LENGTH_SHORT).show();
}
@Override
public void onFail(String msg) {
Toast.makeText(MainActivity.this, url1 + "下载失败", Toast.LENGTH_SHORT).show();
}
});
好了今天就到这里,希望能帮到大家,这对我来说也是一种加深印象的笔记,
下载地址demo
git地址:DownloadManager 欢迎star
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。



