Better error handling for downloads
This commit is contained in:
parent
3b11090e00
commit
260fa59799
4 changed files with 55 additions and 29 deletions
|
@ -168,7 +168,7 @@ public class DownloadManager {
|
|||
try {
|
||||
DiskUtils.createDirectory(download.directory);
|
||||
} catch (IOException e) {
|
||||
Timber.e(e.getMessage());
|
||||
return Observable.error(e);
|
||||
}
|
||||
|
||||
Observable<List<Page>> pageListObservable = download.pages == null ?
|
||||
|
@ -182,34 +182,35 @@ public class DownloadManager {
|
|||
|
||||
return pageListObservable
|
||||
.subscribeOn(Schedulers.io())
|
||||
.doOnNext(pages -> download.downloadedImages = 0)
|
||||
.doOnError(error -> download.setStatus(Download.ERROR))
|
||||
.doOnNext(pages -> download.setStatus(Download.DOWNLOADING))
|
||||
.doOnNext(pages -> download.downloadedImages = 0)
|
||||
// Get all the URLs to the source images, fetch pages if necessary
|
||||
.flatMap(pageList -> Observable.from(pageList)
|
||||
.filter(page -> page.getImageUrl() != null)
|
||||
.mergeWith(download.source.getRemainingImageUrlsFromPageList(pageList)))
|
||||
.flatMap(download.source::getAllImageUrlsFromPageList)
|
||||
// Start downloading images, consider we can have downloaded images already
|
||||
.concatMap(page -> getDownloadedImage(page, download.source, download.directory))
|
||||
.doOnNext(p -> download.downloadedImages++)
|
||||
.concatMap(page -> getOrDownloadImage(page, download))
|
||||
// Do after download completes
|
||||
.doOnCompleted(() -> onDownloadCompleted(download))
|
||||
.toList()
|
||||
.flatMap(pages -> Observable.just(areAllDownloadsFinished()));
|
||||
.flatMap(pages -> Observable.just(download))
|
||||
// If the page list threw, it will resume here
|
||||
.onErrorResumeNext(error -> Observable.just(download))
|
||||
.map(d -> areAllDownloadsFinished());
|
||||
}
|
||||
|
||||
// Get downloaded image if exists, otherwise download it with the method below
|
||||
public Observable<Page> getDownloadedImage(final Page page, Source source, File chapterDir) {
|
||||
Observable<Page> pageObservable = Observable.just(page);
|
||||
// Get the image from the filesystem if it exists or download from network
|
||||
private Observable<Page> getOrDownloadImage(final Page page, Download download) {
|
||||
// If the image URL is empty, do nothing
|
||||
if (page.getImageUrl() == null)
|
||||
return pageObservable;
|
||||
return Observable.just(page);
|
||||
|
||||
String imageFilename = getImageFilename(page);
|
||||
File imagePath = new File(chapterDir, imageFilename);
|
||||
String filename = getImageFilename(page);
|
||||
File imagePath = new File(download.directory, filename);
|
||||
|
||||
if (!isImageDownloaded(imagePath)) {
|
||||
page.setStatus(Page.DOWNLOAD_IMAGE);
|
||||
pageObservable = downloadImage(page, source, chapterDir, imageFilename);
|
||||
}
|
||||
// If the image is already downloaded, do nothing. Otherwise download from network
|
||||
Observable<Page> pageObservable = isImageDownloaded(imagePath) ?
|
||||
Observable.just(page) :
|
||||
downloadImage(page, download.source, download.directory, filename);
|
||||
|
||||
return pageObservable
|
||||
// When the image is ready, set image path, progress (just in case) and status
|
||||
|
@ -217,6 +218,7 @@ public class DownloadManager {
|
|||
p.setImagePath(imagePath.getAbsolutePath());
|
||||
p.setProgress(100);
|
||||
p.setStatus(Page.READY);
|
||||
download.downloadedImages++;
|
||||
})
|
||||
// If the download fails, mark this page as error
|
||||
.doOnError(e -> page.setStatus(Page.ERROR))
|
||||
|
@ -224,20 +226,39 @@ public class DownloadManager {
|
|||
.onErrorResumeNext(e -> Observable.just(page));
|
||||
}
|
||||
|
||||
// Download the image and save it to the filesystem
|
||||
private Observable<Page> downloadImage(final Page page, Source source, File chapterDir, String imageFilename) {
|
||||
private Observable<Page> downloadImage(Page page, Source source, File directory, String filename) {
|
||||
page.setStatus(Page.DOWNLOAD_IMAGE);
|
||||
return source.getImageProgressResponse(page)
|
||||
.flatMap(resp -> {
|
||||
try {
|
||||
DiskUtils.saveBufferedSourceToDirectory(resp.body().source(), chapterDir, imageFilename);
|
||||
} catch (IOException e) {
|
||||
Timber.e(e.fillInStackTrace(), e.getMessage());
|
||||
throw new IllegalStateException("Unable to save image");
|
||||
DiskUtils.saveBufferedSourceToDirectory(resp.body().source(), directory, filename);
|
||||
} catch (Exception e) {
|
||||
return Observable.error(e);
|
||||
}
|
||||
return Observable.just(page);
|
||||
});
|
||||
}
|
||||
|
||||
// Public method to get the image from the filesystem. It does NOT provide any way to download the iamge
|
||||
public Observable<Page> getDownloadedImage(final Page page, File chapterDir) {
|
||||
if (page.getImageUrl() == null) {
|
||||
page.setStatus(Page.ERROR);
|
||||
return Observable.just(page);
|
||||
}
|
||||
|
||||
File imagePath = new File(chapterDir, getImageFilename(page));
|
||||
|
||||
// When the image is ready, set image path, progress (just in case) and status
|
||||
if (isImageDownloaded(imagePath)) {
|
||||
page.setImagePath(imagePath.getAbsolutePath());
|
||||
page.setProgress(100);
|
||||
page.setStatus(Page.READY);
|
||||
} else {
|
||||
page.setStatus(Page.ERROR);
|
||||
}
|
||||
return Observable.just(page);
|
||||
}
|
||||
|
||||
// Get the filename for an image given the page
|
||||
private String getImageFilename(Page page) {
|
||||
String url;
|
||||
|
|
|
@ -97,6 +97,12 @@ public abstract class Source extends BaseSource {
|
|||
});
|
||||
}
|
||||
|
||||
public Observable<Page> getAllImageUrlsFromPageList(final List<Page> pages) {
|
||||
return Observable.from(pages)
|
||||
.filter(page -> page.getImageUrl() != null)
|
||||
.mergeWith(getRemainingImageUrlsFromPageList(pages));
|
||||
}
|
||||
|
||||
// Get the URLs of the images of a chapter
|
||||
public Observable<Page> getRemainingImageUrlsFromPageList(final List<Page> pages) {
|
||||
return Observable.from(pages)
|
||||
|
|
|
@ -149,14 +149,12 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
|||
Observable<Page> pageObservable;
|
||||
|
||||
if (!isDownloaded) {
|
||||
pageObservable = Observable.from(pageList)
|
||||
.filter(page -> page.getImageUrl() != null)
|
||||
.mergeWith(source.getRemainingImageUrlsFromPageList(pageList))
|
||||
pageObservable = source.getAllImageUrlsFromPageList(pageList)
|
||||
.flatMap(source::getCachedImage, 3);
|
||||
} else {
|
||||
File chapterDir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
|
||||
pageObservable = Observable.from(pageList)
|
||||
.flatMap(page -> downloadManager.getDownloadedImage(page, source, chapterDir));
|
||||
.flatMap(page -> downloadManager.getDownloadedImage(page, chapterDir));
|
||||
}
|
||||
return pageObservable
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
|
|
@ -134,8 +134,9 @@ public final class DiskUtils {
|
|||
} catch (Exception e) {
|
||||
if (bufferedSink != null) {
|
||||
bufferedSink.close();
|
||||
writeFile.delete();
|
||||
}
|
||||
writeFile.delete();
|
||||
throw new IOException("Failed saving image");
|
||||
}
|
||||
|
||||
return writeFile;
|
||||
|
|
Reference in a new issue