首先调用是这样的
String url = "https://mac-installer.github.com/mac/GitHub%20Desktop%20220.zip";
subscription = api.downloadFile(url, null, new Subscriber<FileInfo>() {
@Override public void onCompleted() {
L.e(TAG + " down ", Thread.currentThread().getName() + "onCompleted ");
}
@Override public void onError(Throwable e) {
L.e(TAG + " down ", e);
}
@Override public void onNext(FileInfo fileInfo) {
long percent = fileInfo.getCurrentSize() / fileInfo.getFileSize();
L.e(TAG + " down ", fileInfo);
}
});
可以取消订阅,结束下载
@Override protected void onDestroy() {
super.onDestroy();
subscription.unsubscribe();
}
下面的图是下载的 log
下载 log
FileInfo 是这样的
public class FileInfo {
private String fileName;
private String fileUrl;
private String fileType;
private long fileSize;//单位 byte
private long currentSize;
//省略 getter setter
}
下载代码
public Subscription downloadFile(String url,String dest, Subscriber<FileInfo> subscriber) {
return Observable.create(new Observable.OnSubscribe<FileInfo>() {
@Override public void call(Subscriber<? super FileInfo> subscriber) {
if (!subscriber.isUnsubscribed()) {
try {
new FileDownLoader().download(url, dest, subscriber);
} catch (IOException e) {
e.printStackTrace();
subscriber.onError(e);
}
}
}
}).compose(applySchedulers())
.onBackpressureBuffer()// 一定要调用onBackpressureBuffer()方法,防止下载过快,导致MissingBackpressureException异常
.subscribe(subscriber);
}
其中applySchedulers()
public static final Observable.Transformer schedulersTransformer =
new Observable.Transformer<Observable, Observable>() {
@Override public Observable<Observable> call(Observable<Observable> observable) {
return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
};
/**
* 应用 Schedulers .方便 compose() 简化代码
*/
@SuppressWarnings("unchecked") public static <T> Observable.Transformer<T, T> applySchedulers() {
return (Observable.Transformer<T, T>) schedulersTransformer;
}
关键的下载文件FileDownLoader
public class FileDownLoader {
public static final String APK = "application/vnd.android.package-archive";
public static final String PDF = "application/pdf";
public static final String ZIP = "application/zip, application/x-compressed-zip";
private OkHttpClient mClient;
public FileDownLoader() {
mClient = new OkHttpClient.Builder().build();
}
public void download(@NonNull String url, @Nullable String dest,
Subscriber<? super FileInfo> subscriber) throws IOException {
if (!URLUtil.isNetworkUrl(url)) {
throw new RuntimeException("invalid url");
}
Uri uri = Uri.parse(url);
String filename = uri.getLastPathSegment();// get fileName
File root;
if (!TextUtils.isEmpty(dest)) {
root = new File(dest);
} else {
root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
}
if (!root.exists()) {
root.mkdirs();
}
File output = new File(root, filename);
if (output.exists()) {
output.delete();
}
Request request = new Request.Builder().url(uri.toString()).build();
Response response = mClient.newCall(request).execute();
long contentLength = response.body().contentLength();
// fill fileInfo
FileInfo currentFile = new FileInfo();
currentFile.setFileSize(contentLength);
currentFile.setFileName(filename);
currentFile.setFileUrl(url);
currentFile.setFileType(response.body().contentType().type());
BufferedSink sink = Okio.buffer(Okio.sink(output));
Buffer buffer = sink.buffer();
long total = 0;
long len;
int bufferSize = 200 * 1024; //200kb
BufferedSource source = response.body().source();
while ((len = source.read(buffer, bufferSize)) != -1) {
sink.emit();
total += len;
currentFile.setCurrentSize(total);
subscriber.onNext(currentFile);// onNext
}
source.close();
sink.close();
subscriber.onCompleted();
}
}