|
@@ -2,7 +2,6 @@ package com.benyanyi.okhttp.download;
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
|
-
|
|
|
import com.benyanyi.okhttp.listener.OnDownLoadObserver;
|
|
|
|
|
|
import java.io.File;
|
|
@@ -37,6 +36,7 @@ class DownloadManager {
|
|
|
* 用来存放各个下载的请求
|
|
|
*/
|
|
|
private HashMap<String, Call> downCalls;
|
|
|
+ private HashMap<String, DownloadInfo> downInfos;
|
|
|
/**
|
|
|
* OKHttpClient;
|
|
|
*/
|
|
@@ -66,6 +66,7 @@ class DownloadManager {
|
|
|
|
|
|
private DownloadManager(Context mContext) {
|
|
|
downCalls = new HashMap<>();
|
|
|
+ downInfos = new HashMap<>();
|
|
|
mClient = new OkHttpClient.Builder().build();
|
|
|
this.mContext = mContext;
|
|
|
}
|
|
@@ -89,44 +90,95 @@ class DownloadManager {
|
|
|
* @param onDownLoadObserver 用来回调的接口
|
|
|
*/
|
|
|
void download(String url, OnDownLoadObserver onDownLoadObserver) {
|
|
|
- Observable.just(url)
|
|
|
- //call的map已经有了,就证明正在下载,则这次不下载
|
|
|
- .filter(new Predicate<String>() {
|
|
|
- @Override
|
|
|
- public boolean test(String s) throws Exception {
|
|
|
- return !downCalls.containsKey(s);
|
|
|
- }
|
|
|
- })
|
|
|
- .flatMap(new Function<String, ObservableSource<?>>() {
|
|
|
- @Override
|
|
|
- public ObservableSource<?> apply(String s) throws Exception {
|
|
|
- return Observable.just(createDownInfo(s));
|
|
|
- }
|
|
|
- })
|
|
|
- //检测本地文件夹,生成新的文件名
|
|
|
- .map(new Function<Object, DownloadInfo>() {
|
|
|
- @Override
|
|
|
- public DownloadInfo apply(Object o) throws Exception {
|
|
|
- return getRealFileName((DownloadInfo) o);
|
|
|
- }
|
|
|
- })
|
|
|
- //下载
|
|
|
- .flatMap(new Function<DownloadInfo, ObservableSource<DownloadInfo>>() {
|
|
|
- @Override
|
|
|
- public ObservableSource<DownloadInfo> apply(DownloadInfo downloadInfo) throws Exception {
|
|
|
- return Observable.create(new DownloadSubscribe(downloadInfo));
|
|
|
- }
|
|
|
- })
|
|
|
- //在主线程回调
|
|
|
- .observeOn(AndroidSchedulers.mainThread())
|
|
|
- //在子线程执行
|
|
|
- .subscribeOn(Schedulers.io())
|
|
|
- //添加观察者
|
|
|
- .subscribe(onDownLoadObserver);
|
|
|
+ if (!downCalls.containsKey(url)) {
|
|
|
+ Observable.just(url)
|
|
|
+ //call的map已经有了,就证明正在下载,则这次不下载
|
|
|
+ .filter(new Predicate<String>() {
|
|
|
+ @Override
|
|
|
+ public boolean test(String s) throws Exception {
|
|
|
+ return !downCalls.containsKey(s);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .flatMap(new Function<String, ObservableSource<?>>() {
|
|
|
+ @Override
|
|
|
+ public ObservableSource<?> apply(String s) throws Exception {
|
|
|
+ return Observable.just(createDownInfo(s));
|
|
|
+ }
|
|
|
+ })
|
|
|
+ //检测本地文件夹,生成新的文件名
|
|
|
+ .map(new Function<Object, DownloadInfo>() {
|
|
|
+ @Override
|
|
|
+ public DownloadInfo apply(Object o) throws Exception {
|
|
|
+ return getRealFileName((DownloadInfo) o);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ //下载
|
|
|
+ .flatMap(new Function<DownloadInfo, ObservableSource<DownloadInfo>>() {
|
|
|
+ @Override
|
|
|
+ public ObservableSource<DownloadInfo> apply(DownloadInfo downloadInfo) throws Exception {
|
|
|
+ return Observable.create(new DownloadSubscribe(downloadInfo));
|
|
|
+ }
|
|
|
+ })
|
|
|
+ //在主线程回调
|
|
|
+ .observeOn(AndroidSchedulers.mainThread())
|
|
|
+ //在子线程执行
|
|
|
+ .subscribeOn(Schedulers.io())
|
|
|
+ //添加观察者
|
|
|
+ .subscribe(onDownLoadObserver);
|
|
|
+ } else {
|
|
|
+// Call call = downCalls.get(url);
|
|
|
+// if (call != null) {
|
|
|
+// call.cancel();
|
|
|
+// }
|
|
|
+ Observable.just(url)
|
|
|
+ .flatMap(new Function<String, ObservableSource<DownloadInfo>>() {
|
|
|
+ @Override
|
|
|
+ public ObservableSource<DownloadInfo> apply(String s) throws Exception {
|
|
|
+ return Observable.create(new DownloadingSubscribe(s));
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .subscribeOn(Schedulers.io())
|
|
|
+ .observeOn(AndroidSchedulers.mainThread())
|
|
|
+ .subscribe(onDownLoadObserver);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * 暂停
|
|
|
+ *
|
|
|
+ * @param url
|
|
|
+ */
|
|
|
+ void pause(String url) {
|
|
|
+ remove(url);
|
|
|
+ downInfos.remove(url);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 取消
|
|
|
+ *
|
|
|
+ * @param url
|
|
|
+ */
|
|
|
void cancel(String url) {
|
|
|
+ remove(url);
|
|
|
+ SecurityManager checker = new SecurityManager();
|
|
|
+ DownloadInfo downloadInfo = downInfos.get(url);
|
|
|
+ if (downloadInfo != null && downloadInfo.getFile() != null) {
|
|
|
+ File file = downloadInfo.getFile();
|
|
|
+ if (file.exists()) {
|
|
|
+ checker.checkDelete(file.toString());
|
|
|
+ if (file.isFile()) {
|
|
|
+ try {
|
|
|
+ file.delete();
|
|
|
+ } catch (SecurityException se) {
|
|
|
+ se.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ downInfos.remove(url);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void remove(String url) {
|
|
|
Call call = downCalls.get(url);
|
|
|
if (call != null) {
|
|
|
call.cancel();//取消
|
|
@@ -170,7 +222,7 @@ class DownloadManager {
|
|
|
fileNameOther = fileName.substring(0, dotIndex)
|
|
|
+ "(" + i + ")" + fileName.substring(dotIndex);
|
|
|
}
|
|
|
- File newFile = new File(savePath, fileNameOther + suffix);
|
|
|
+ File newFile = new File(savePath, fileNameOther);
|
|
|
file = newFile;
|
|
|
downloadLength = newFile.length();
|
|
|
i++;
|
|
@@ -207,6 +259,7 @@ class DownloadManager {
|
|
|
Call call = mClient.newCall(request);
|
|
|
//把这个添加到call里,方便取消
|
|
|
downCalls.put(url, call);
|
|
|
+ downInfos.put(url, downloadInfo);
|
|
|
Response response = call.execute();
|
|
|
String savePath = FileUtil.isExistDir(mContext.getPackageName());
|
|
|
File file = new File(savePath, downloadInfo.getFileName());
|
|
@@ -222,6 +275,7 @@ class DownloadManager {
|
|
|
fileOutputStream.write(buffer, 0, len);
|
|
|
downloadLength += len;
|
|
|
downloadInfo.setProgress(downloadLength);
|
|
|
+ downInfos.put(url, downloadInfo);
|
|
|
e.onNext(downloadInfo);
|
|
|
}
|
|
|
downloadInfo.setFile(file);
|
|
@@ -235,6 +289,57 @@ class DownloadManager {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private class DownloadingSubscribe implements ObservableOnSubscribe<DownloadInfo> {
|
|
|
+
|
|
|
+ private String url;
|
|
|
+
|
|
|
+ DownloadingSubscribe(String url) {
|
|
|
+ this.url = url;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void subscribe(ObservableEmitter<DownloadInfo> e) throws Exception {
|
|
|
+ DownloadInfo downloadInfo = downInfos.get(url);
|
|
|
+ //已经下载好的长度
|
|
|
+ long downloadLength = downloadInfo.getProgress();
|
|
|
+ //初始进度信息
|
|
|
+ e.onNext(downloadInfo);
|
|
|
+
|
|
|
+ //把这个添加到call里,方便取消
|
|
|
+ Call call = downCalls.get(url);
|
|
|
+ if (call != null) {
|
|
|
+ Response response = call.execute();
|
|
|
+ String savePath = FileUtil.isExistDir(mContext.getPackageName());
|
|
|
+ File file = new File(savePath, downloadInfo.getFileName());
|
|
|
+ InputStream is = null;
|
|
|
+ FileOutputStream fileOutputStream = null;
|
|
|
+ try {
|
|
|
+ is = response.body().byteStream();
|
|
|
+ fileOutputStream = new FileOutputStream(file, true);
|
|
|
+ //缓冲数组2kB
|
|
|
+ byte[] buffer = new byte[2048];
|
|
|
+ int len;
|
|
|
+ while ((len = is.read(buffer)) != -1) {
|
|
|
+ fileOutputStream.write(buffer, 0, len);
|
|
|
+ downloadLength += len;
|
|
|
+ downloadInfo.setProgress(downloadLength);
|
|
|
+ downInfos.put(url, downloadInfo);
|
|
|
+ e.onNext(downloadInfo);
|
|
|
+ }
|
|
|
+ downloadInfo.setFile(file);
|
|
|
+ fileOutputStream.flush();
|
|
|
+ downCalls.remove(url);
|
|
|
+ } finally {
|
|
|
+ //关闭IO流
|
|
|
+ IoUtil.closeAll(is, fileOutputStream);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ e.onError(new Throwable("下载失败"));
|
|
|
+ }
|
|
|
+ e.onComplete();//完成
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 获取下载长度
|
|
|
*
|