ssseasonnn / rxdownload Goto Github PK
View Code? Open in Web Editor NEWA multi-threaded download tool written with RxJava and Kotlin
License: Apache License 2.0
A multi-threaded download tool written with RxJava and Kotlin
License: Apache License 2.0
请问有什么方法可以获取到使用的okhttpClient呢,因为需要对okhttpClient写一些通用的intercepter
很不错,求大神能加个文件上传的功能,带进度显示
多次调用下载方法时,如果已存在该下载任务,则会直接抛异常。
=> 是否可以改为:已存在下载任务,则监听上次下载的状态。
比如这样的场景:
需要下载一个配置文件,可能在A位置或B位置 开始下载,AB位置需要同时显示下载状态。
如果所有类似场景都自己去判断,那代码必然变得很臃肿。
而且,如果在调用download() 之前没有去判断是否存在该任务,基本都是不太关心是否有存在相同任务的,只是希望把文件下载回来,调用download()后能监听到文件的下载情况。
I saw the getWhenFileExists
function as follow:
private Observable<DownloadType> getWhenFileExists(final String url) throws IOException {
return getDownloadApi()
.getHttpHeaderWithIfRange(TEST_RANGE_SUPPORT, getLastModify(url), url)
.map(new Function<Response<Void>, DownloadType>() {
@Override
public DownloadType apply(Response<Void> resp) throws Exception {
if (Utils.serverFileNotChange(resp)) {
return getWhenServerFileNotChange(resp, url);
} else if (Utils.serverFileChanged(resp)) {
return getWhenServerFileChanged(resp, url);
} else if (Utils.requestRangeNotSatisfiable(resp)) {
return mFactory.url(url)
.fileLength(Utils.contentLength(resp))
.lastModify(Utils.lastModify(resp))
.buildRequestRangeNotSatisfiable();
} else {
throw new RuntimeException("unknown error"); //<==throwing a RuntimeException is somewhat weird
}
}
})
.retry(new BiPredicate<Integer, Throwable>() {
@Override
public boolean test(Integer integer, Throwable throwable) throws Exception {
return retry(integer, throwable);
}
});
}
Throwing a RuntimeException
to notify the subscriber is somewhat weird.
I suggest that we should add a UnableDownloadType
class to indicate the http response cannot support downloading, and return a UnableDownloadType
instance here. When we are processing DownloadType
, if the download type is UnableDownloadType
, we throw a specific Exception as like UnableDownloadException
:
getDownloadType(url)
.flatMap(new Function<DownloadType, ObservableSource<DownloadStatus>>() {
@Override
public ObservableSource<DownloadStatus> apply(DownloadType downloadType) throws Exception {
if (downloadType instanceof UnableDownloadType) { //<==check the download type
throw new UnableDownloadException(...)
} else {
downloadType.prepareDownload();
return downloadType.startDownload();
}
}
})
ava.lang.IllegalArgumentException: Missing either @Head URL or @url parameter.
for method a.b
retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:720)
retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:711)
retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:206)
retrofit2.Retrofit.loadServiceMethod(Retrofit.java:166)
retrofit2.Retrofit$1.invoke(Retrofit.java:145)
java.lang.reflect.Proxy.invoke(Proxy.java:397)
$Proxy1.b(Unknown Source)
zlc.season.rxdownload2.function.b.f(DownloadHelper.java:324)
zlc.season.rxdownload2.function.b.e(DownloadHelper.java:318)
zlc.season.rxdownload2.function.b.a(DownloadHelper.java:158)
zlc.season.rxdownload2.function.DownloadService$b.run(DownloadService.java:1306)
java.lang.Thread.run(Thread.java:818)
android library 的 manifest 文件不需要配置多余的属性,像android:allowBackup="true"
,个人建议去掉
做了一个类似于应用市场的demo,发现下载好的应用或已安装的应用,再次根据 url 去 receiveDownloadStatus ,第一次发射的状态是 NORMAL,建议根据应用是否安装,文件是否存在 发射 已安装,已完成。不然每次都要取下载记录。
我看了一下代码, 这里两个地方:
一个是: 下载完后, 在流还未关完的情况下, 就进行了onComplete, 这样子有一些不妥当. 最好是在流关闭完后, 再进行onComplete;
一个是: 因为不是在流关闭后进行onComplete, 所以在doOnCompleted中, 等待1.5s再执行其它的事后操作. 这种方式有一些被动.
https下载300M左右的视频,暂停以后就无法继续下载了
现在使用你们这个下载功能集成到listview中,每个item有一个下载按扭,点击后显示百分比进度,但现在看来有点卡,有什么好的解决办法。
点击下载 界面特别卡请问库当中有哪个方法可以解决
RT
private class DownloadMissionDispatchRunnable implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
DownloadMission mission = mWaitingForDownload.peek();
if (null != mission) {
...
}
}
}
}
这里的mWaitingForDownload = new LinkedList<>()不是阻塞队列,while相当于一个死循环。
导致这个服务在后台跑时相当费电。
mWaitingForDownload应该是一个BlockingQueue才对的
Code:
disposable = RxDownload.getInstance(this)
.maxThread(5)//5线程
.maxRetryCount(3)//错误重试次数
.download(currentUrl)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<DownloadStatus>() {
@Override
public void accept(@NonNull DownloadStatus status) throws Exception {
Logger.d("RxDownload信息...DownloadSize:" + status.getDownloadSize() + "...TotalSize" + status.getTotalSize() + "...Percent" + status.getPercentNumber());
pbDownload.setProgress((int) status.getPercentNumber());
tvNetSpeed.setText(status.getFormatDownloadSize() + "/" + status.getFormatTotalSize());
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
Logger.d("RxDownload信息...onError");
throwable.printStackTrace();
}
}, new Action() {
@Override
public void run() throws Exception {
long time = System.currentTimeMillis() - startTime;
long resultTime = time / 1000;
Logger.d("RxDownload信息...onComplete:耗时" + resultTime);
}
});
Exception:
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Download/.cache/3c5d8fe0-4f1d-4f4e-b7c5-59f2c4b4e9fd.apk.lmf: open failed: ENOENT (No such file or directory)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at libcore.io.IoBridge.open(IoBridge.java:455)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at java.io.RandomAccessFile.<init>(RandomAccessFile.java:247)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at zlc.season.rxdownload2.function.FileHelper.writeLastModify(FileHelper.java:295)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at zlc.season.rxdownload2.function.FileHelper.prepareDownload(FileHelper.java:107)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at zlc.season.rxdownload2.entity.TemporaryRecord.prepareRangeDownload(TemporaryRecord.java:113)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at zlc.season.rxdownload2.entity.DownloadType$MultiThreadDownload.prepareDownload(DownloadType.java:297)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at zlc.season.rxdownload2.function.DownloadHelper.download(DownloadHelper.java:134)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at zlc.season.rxdownload2.function.DownloadHelper.access$200(DownloadHelper.java:43)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at zlc.season.rxdownload2.function.DownloadHelper$3.apply(DownloadHelper.java:115)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at zlc.season.rxdownload2.function.DownloadHelper$3.apply(DownloadHelper.java:112)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onNext(ObservableFlatMap.java:121)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.tryEmit(ObservableFlatMap.java:262)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$InnerObserver.onNext(ObservableFlatMap.java:554)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.drainLoop(ObservableFlatMap.java:434)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.drain(ObservableFlatMap.java:323)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$InnerObserver.onSubscribe(ObservableFlatMap.java:541)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarXMapObservable.subscribeActual(ObservableScalarXMap.java:163)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.subscribeInner(ObservableFlatMap.java:162)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onNext(ObservableFlatMap.java:139)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableDoOnEach$DoOnEachObserver.onNext(ObservableDoOnEach.java:103)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.tryEmit(ObservableFlatMap.java:262)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$InnerObserver.onNext(ObservableFlatMap.java:554)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableRetryBiPredicate$RetryBiObserver.onNext(ObservableRetryBiPredicate.java:66)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:64)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableDoOnEach$DoOnEachObserver.onNext(ObservableDoOnEach.java:103)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at com.jakewharton.retrofit2.adapter.rxjava2.CallObservable.subscribeActual(CallObservable.java:43)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableDoOnEach.subscribeActual(ObservableDoOnEach.java:42)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableMap.subscribeActual(ObservableMap.java:33)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableRetryBiPredicate$RetryBiObserver.subscribeNext(ObservableRetryBiPredicate.java:100)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableRetryBiPredicate.subscribeActual(ObservableRetryBiPredicate.java:39)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.subscribeInner(ObservableFlatMap.java:162)
03-08 16:23:05.185 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onNext(ObservableFlatMap.java:139)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableRetryBiPredicate$RetryBiObserver.onNext(ObservableRetryBiPredicate.java:66)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:64)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableDoOnEach$DoOnEachObserver.onNext(ObservableDoOnEach.java:103)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at com.jakewharton.retrofit2.adapter.rxjava2.CallObservable.subscribeActual(CallObservable.java:43)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableDoOnEach.subscribeActual(ObservableDoOnEach.java:42)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableMap.subscribeActual(ObservableMap.java:33)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableRetryBiPredicate$RetryBiObserver.subscribeNext(ObservableRetryBiPredicate.java:100)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableRetryBiPredicate.subscribeActual(ObservableRetryBiPredicate.java:39)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarXMapObservable.subscribeActual(ObservableScalarXMap.java:166)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:55)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableDoOnEach.subscribeActual(ObservableDoOnEach.java:42)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:55)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.subscribeInner(ObservableFlatMap.java:162)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onNext(ObservableFlatMap.java:139)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.observers.DisposableLambdaObserver.onNext(DisposableLambdaObserver.java:59)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarDisposable.run(ObservableScalarXMap.java:248)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableJust.subscribeActual(ObservableJust.java:35)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableDoOnLifecycle.subscribeActual(ObservableDoOnLifecycle.java:33)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:55)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableFlatMap.subscribeActual(ObservableFlatMap.java:55)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableDoOnEach.subscribeActual(ObservableDoOnEach.java:42)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.186 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableDoFinally.subscribeActual(ObservableDoFinally.java:45)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Observable.subscribe(Observable.java:10700)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.operators.observable.ObservableSubscribeOn$1.run(ObservableSubscribeOn.java:39)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.Scheduler$1.run(Scheduler.java:138)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at java.lang.Thread.run(Thread.java:776)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at libcore.io.Posix.open(Native Method)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:187)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: at libcore.io.IoBridge.open(IoBridge.java:441)
03-08 16:23:05.187 29448-29448/com.floatingmuseum.androidtest W/System.err: ... 81 more
I found there no .cache dir in Download directory
感谢大大!
Here is the PR! #29
I think it should be a good start for the documentation to support multiple language!
我用下面这种代码在fragment中使用,有时下载完成了不回调onsuccess反而回调onerror这是什么原因啊
RxPermissions.getInstance(mContext)
.request(WRITE_EXTERNAL_STORAGE)
.doOnNext(new Consumer<Boolean>() })
.observeOn(Schedulers.io())
.compose(rxDownload.<Boolean>transform(...)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<DownloadStatus>() {
@Override
public void onSubscribe(Disposable d) {
//
}
@Override
public void onNext(DownloadStatus status) { }
@Override
public void onError(Throwable e) { }
@Override
public void onComplete() { }
});
上传JCenter的时候,compile写成provided,
然后告诉使用者自己去添加哪些依赖库会灵活点。
当然你现在用的参数配置的法子也不是不行,只是个人建议~:smile:
03-23 14:46:27.435 17450-17528/com.example.sand.rxjava I/RxDownload: Mission coming!
03-23 14:46:27.451 17450-17528/com.example.sand.rxjava I/RxDownload: DownloadQueue waiting for mission come...
03-23 14:46:27.534 17450-17527/com.example.sand.rxjava V/RenderScript: Application requested CPU execution
03-23 14:46:27.539 17450-17527/com.example.sand.rxjava V/RenderScript: 0xaf75ee00 Launching thread(s), CPUs 4
点了下载后就这样,没有进度也没有开始下载,按照md中教程写的
那如果我下次需要得到已经下载和未完成的,是不是需要自己查询数据库呢?若sevice异常关闭,数据库会有问题不?
需求是在退出应用的时候判断是否要继续下载,所以能否判断是否有文件正在下载?应该加上判断数据库正在下载的记录是不是大于0就好了吧?
连续点击开始暂停开始暂停下载,会出现一下就下载完的bug,但是其实是没下载完的,下载下来的安装包大小虽然显示是正确的大小,但是是安装不了的,可以在demo里面试试。
我用的是这个链接,不支持断点的:
http://d.static.myappgame.com/qiu-fu-mo-lan-dan-dan-duo-dian-jiang-you-14571945118/qiu-fu-mo-lan-dan-dan-duo-dian-jiang-you-20170320.apk
mRxDownload.serviceDownload(url, saveName, savePath)
.subscribe(new Action1<Object>() {
这种下载的时候怎么加权限
// RxPermissions.getInstance(this)
// .request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
// .doOnNext(new Action1() {
// @OverRide
// public void call(Boolean granted) {
// if (!granted) {
// Toast.makeText(musicApplication, "ھوقۇقنى تەمىنلىمەپسىز", Toast.LENGTH_SHORT).show();
// throw new RuntimeException("no permission");
// }
// }
// })
这个功能怎么实现
您好,大神,我想问下你这断点下载具体怎么实现的啊?我没怎么看懂,当暂停时,上次的下载进度大小在哪里记录的?然后传入到下次继续下载里
因为我也在做一个文件下载库
SimpleDownloader
因为SQLite并不支持并发写入,所以我在写入方法上加上synchronized,但是考虑到可能存在的效率问题,所以又把写入操作的参数放入message然后传到Handler消息队列中,结果在测试的时候发现虽然安全性保证,但写入效率更低。最后改为将文件分片,然后根据每个文件片的长度来判定断点下载的开始位置。
我学习了下您的代码,发现您没有对数据库的写入加锁也没有合并成事务而是直接操作,当任务线程增多(比如上百个)的情况下会不会有问题呢?想和您交流一下
servicedownload()方法下载过程中,下载进度跳动.
比如说:下载到67%突然跳到47%了,下载了一会儿后又跳到75%
大神,求加上多任务上传的功能呢
你好,我在使用该库的时候,发现 DownloadService 启动的 DownloadMissionDispatchRunnable 线程是无法在 RxDownload 中控制的,是否可以在 RxDownload 中增加一个控制 DownloadService 的方法(检查服务状态、开启、关闭)呢?
另外,还有一个小问题,RxIoScheduler-(.*) 这些下载线程里面,会出现最后一个线程的下载速度非常慢,通常一个50MB的文件,用浏览器下载是在10秒内,但是使用RxDownload下载需要30-40秒才完成。原因就是最后启动的一个 RxIoScheduler 线程速度非常慢。
批量下载,怎么添加到数据库,能在列表显示出来?
导入时报这个错误是什么原因plugin with id 'android-apt' not found.
使用Retorfit+Rxjava结合时,只能使用Retorfit2+Rxjava1,使用Rxjava2会包冲突,希望作者能继续维护使用Rxjava1跟官方同步。
像我这种菜鸟看起开会很吃力 @ssseasonnn
应用下载暂停继续 会发现点击继续后 不会下载
是否可以设置最大下载数量,比如下载数量 为2,其他下载的显示为等待状态
更新进度条时 不是连续的,是跳跃似的更新,
我在测试过程中进行多线程多任务下载发现有些任务的下载进度会超过100%,请问一下是否是多线程导致的问题?
在7.0系统下需使用FileProvider来处理文件路径问题
使用getDownloadRecord方法如果没有下载过,数据库没有记录onnext方法不会调用。
public Observable readRecord(final String url) {
return Observable.create(new Observable.OnSubscribe() {
@OverRide
public void call(Subscriber<? super DownloadRecord> subscriber) {
Cursor cursor = null;
try {
cursor = getReadableDatabase().rawQuery("select * from " + TABLE_NAME +
" where " + "url=?", new String[]{url});
while (cursor.moveToNext()) {
subscriber.onNext(Db.RecordTable.read(cursor));
}
subscriber.onCompleted();
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
cursor.moveToNext()为false的时候没有onnext的调用只有onCompleted
获取不到文件的状态。
12-14 20:17:01.031 14896-15081/com.star.app.tvhelper.ui.shanxi W/RxDownload: java.lang.IllegalStateException: Context is NULL! You should call #RxDownload.context(Context context)# first!
at zlc.season.rxdownload.RxDownload$11.call(RxDownload.java:430)
at rx.internal.util.ActionObserver.onCompleted(ActionObserver.java:49)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onCompleted(OnSubscribeDoOnEach.java:63)
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:656)
at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568)
at rx.internal.operators.OperatorMerge$MergeProducer.request(OperatorMerge.java:133)
at rx.internal.operators.OperatorSubscribeOn$1$1$1$1.call(OperatorSubscribeOn.java:85)
at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:228)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1115)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:590)
at java.lang.Thread.run(Thread.java:818)
请问有什么方法可以获取到使用的okhttpClient呢,因为需要对okhttpClient写一些通用的intercepter
启动下载到下载完成后,下次启动不知道是否下载成功,重试下载后重新开始下载了。
希望能自动检测如果下载成功过,就不在重新下载了。
java.lang.RuntimeException: unknown error
at zlc.season.rxdownload.RxDownload$16.call(RxDownload.java:510)
at zlc.season.rxdownload.RxDownload$16.call(RxDownload.java:502)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:69)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:173)
at rx.internal.producers.ProducerArbiter.setProducer(ProducerArbiter.java:126)
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1$1.setProducer(OperatorRetryWithPredicate.java:122)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.setProducer(OnSubscribeMap.java:102)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:127)
at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:73)
at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:52)
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:79)
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45)
at rx.internal.util.ScalarSynchronousObservable$WeakSingleProducer.request(ScalarSynchronousObservable.java:276)
at rx.Subscriber.setProducer(Subscriber.java:209)
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:138)
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:129)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10151)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:228)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: rx.excepti
我们有些文件需要先验证,通过了验证才能下载
所以问问这个项目支不支持302
在设置同时只进行1个任务进行下时,快速乱序的点击多个任务的暂停和继续按钮,会出现下载队列异常,导致出现多个任务同时下载的情况。且部分任务出现无法暂停的情况。
调用代码:
Subscription subscription = rxDownload.download(url, fileName, savePath)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<DownloadStatus>() {
@Override
public void onCompleted() {
//下载完成
...
}
@Override
public void onError(Throwable e) {
//下载出错
...
}
@Override
public void onNext(final DownloadStatus status) {
//下载状态
...
}
});
错误日志:
rx.exceptions.MissingBackpressureException
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.onNext(OperatorObserveOn.java:160)
at rx.internal.operators.OperatorUnsubscribeOn$1.onNext(OperatorUnsubscribeOn.java:52)
at rx.internal.operators.OperatorSubscribeOn$1$1.onNext(OperatorSubscribeOn.java:53)
at rx.observers.Subscribers$5.onNext(Subscribers.java:235)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onNext(OnSubscribeDoOnEach.java:101)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onNext(OnSubscribeDoOnEach.java:101)
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitScalar(OperatorMerge.java:395)
at rx.internal.operators.OperatorMerge$MergeSubscriber.tryEmit(OperatorMerge.java:355)
at rx.internal.operators.OperatorMerge$InnerSubscriber.onNext(OperatorMerge.java:846)
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1$1.onNext(OperatorRetryWithPredicate.java:115)
at rx.internal.operators.OperatorOnBackpressureLatest$LatestEmitter.emit(OperatorOnBackpressureLatest.java:165)
at rx.internal.operators.OperatorOnBackpressureLatest$LatestEmitter.onNext(OperatorOnBackpressureLatest.java:131)
at rx.internal.operators.OperatorOnBackpressureLatest$LatestSubscriber.onNext(OperatorOnBackpressureLatest.java:211)
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitScalar(OperatorMerge.java:395)
at rx.internal.operators.OperatorMerge$MergeSubscriber.tryEmit(OperatorMerge.java:355)
at rx.internal.operators.OperatorMerge$InnerSubscriber.onNext(OperatorMerge.java:846)
at zlc.season.rxdownload.function.FileHelper.saveFile(FileHelper.java:142)
at zlc.season.rxdownload.function.DownloadHelper.saveNormalFile(DownloadHelper.java:152)
at zlc.season.rxdownload.entity.DownloadType$NormalDownload$1.call(DownloadType.java:48)
at zlc.season.rxdownload.entity.DownloadType$NormalDownload$1.call(DownloadType.java:45)
at rx.Observable.unsafeSubscribe(Observable.java:10142)
at rx.internal.operators.OperatorMerge$MergeSubscriber.onNext(OperatorMerge.java:248)
at rx.internal.operators.OperatorMerge$MergeSubscriber.onNext(OperatorMerge.java:148)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:77)
at rx.internal.operators.OperatorSubscribeOn$1$1.onNext(OperatorSubscribeOn.java:53)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:173)
at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
at rx.Subscriber.setProducer(Subscriber.java:211)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.setProducer(OnSubscribeMap.java:102)
at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
at rx.Observable.unsafeSubscribe(Observable.java:10142)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:230)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
我认为 DataBaseHelper 类中 readRecord 方法的实现不是很好。
现有方式:
当数据库找不到相应数据,是直接调用 subscriber.onCompleted(),没有调用 subscriber.onNext() 方法。
会出现的问题:
当对 RxDownload.getDownloadRecord() 返回的 Observable 对象使用 subscribe(new Action1() {...}) 方法订阅时,会无法触发 call() ,这样没办法很好地结合其它 Observable 做链式处理(map、concatMap指令等等)
想法:
在 readRecord 方法中,增加 subscriber.onNext() 的调用,例如:
cursor = getReadableDatabase().rawQuery("select * from " + TABLE_NAME + " where " + "url=?", new String[]{url});
if (cursor.moveToNext()) {
subscriber.onNext(Db.RecordTable.read(cursor));
while (cursor.moveToNext()) {
subscriber.onNext(Db.RecordTable.read(cursor));
}
} else {
subscriber.onNext(null);
}
subscriber.onCompleted();
你好,我的需求是同时下载多个文件,每下完一个文件在数据库作记录,于是我onCompleted中记录该文件已下载,结果我发现数据库中的记录与下载的文件不一致。是我哪里操作不当吗?望大神指教。
我原项目中使用的是Rx1.0的库,然而你这个项目自带了RX2.0的库依赖冲突了有办法解决吗?是否可以灵活配置所使用的Rx库!
public static void mkdirs(String... paths) throws IOException {
for (String each : paths) {
File file = new File(each);
if (file.exists() && file.isDirectory()) {
log(DIR_EXISTS_HINT, each);
} else {
log(DIR_NOT_EXISTS_HINT, each);
boolean flag = file.mkdir(); // 这里推荐使用mkdirs,防止父文件夹不存在的情况
if (flag) {
log(DIR_CREATE_SUCCESS, each);
} else {
log(DIR_CREATE_FAILED, each);
throw new IOException(format(getDefault(), DIR_CREATE_FAILED, each));
}
}
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.