Browse Source

Avoid filename conflicts (not sure if it will be totally fixed). Check if a chapter is properly downloaded after download finishes.

inorichi 9 years ago
parent
commit
c52c567eae

+ 5 - 12
app/src/main/java/eu/kanade/mangafeed/data/cache/CacheManager.java

@@ -179,7 +179,7 @@ public class CacheManager {
         return null;
     }
 
-    public boolean putImageToDiskCache(final String imageUrl, final Response response) {
+    public void putImageToDiskCache(final String imageUrl, final Response response) throws IOException {
         DiskLruCache.Editor editor = null;
         BufferedSink sink = null;
 
@@ -187,33 +187,26 @@ public class CacheManager {
             String key = DiskUtils.hashKeyForDisk(imageUrl);
             editor = mDiskCache.edit(key);
             if (editor == null) {
-                return false;
+                throw new IOException("Unable to edit key");
             }
 
             OutputStream outputStream = new BufferedOutputStream(editor.newOutputStream(0));
             sink = Okio.buffer(Okio.sink(outputStream));
             sink.writeAll(response.body().source());
-            sink.flush();
 
             mDiskCache.flush();
             editor.commit();
-        } catch (IOException e) {
-            e.printStackTrace();
-            return false;
+        } catch (Exception e) {
+            throw new IOException("Unable to save image");
         } finally {
             if (editor != null) {
                 editor.abortUnlessCommitted();
             }
             if (sink != null) {
-                try {
-                    sink.close();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
+                sink.close();
             }
         }
 
-        return true;
     }
 
 }

+ 17 - 16
app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java

@@ -12,8 +12,6 @@ import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.lang.reflect.Type;
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.util.List;
 
 import eu.kanade.mangafeed.data.database.models.Chapter;
@@ -27,6 +25,7 @@ import eu.kanade.mangafeed.data.source.model.Page;
 import eu.kanade.mangafeed.event.DownloadChaptersEvent;
 import eu.kanade.mangafeed.util.DiskUtils;
 import eu.kanade.mangafeed.util.DynamicConcurrentMergeOperator;
+import eu.kanade.mangafeed.util.UrlUtil;
 import rx.Observable;
 import rx.Subscription;
 import rx.android.schedulers.AndroidSchedulers;
@@ -81,6 +80,7 @@ public class DownloadManager {
                 .lift(new DynamicConcurrentMergeOperator<>(this::downloadChapter, threadsNumber))
                 .onBackpressureBuffer()
                 .observeOn(AndroidSchedulers.mainThread())
+                .map(download -> areAllDownloadsFinished())
                 .subscribe(finished -> {
                     if (finished) {
                         DownloadService.stop(context);
@@ -164,7 +164,7 @@ public class DownloadManager {
     }
 
     // Download the entire chapter
-    private Observable<Boolean> downloadChapter(Download download) {
+    private Observable<Download> downloadChapter(Download download) {
         try {
             DiskUtils.createDirectory(download.directory);
         } catch (IOException e) {
@@ -182,7 +182,6 @@ public class DownloadManager {
 
         return pageListObservable
                 .subscribeOn(Schedulers.io())
-                .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
@@ -194,8 +193,10 @@ public class DownloadManager {
                 .toList()
                 .flatMap(pages -> Observable.just(download))
                 // If the page list threw, it will resume here
-                .onErrorResumeNext(error -> Observable.just(download))
-                .map(d -> areAllDownloadsFinished());
+                .onErrorResumeNext(error -> {
+                    download.setStatus(Download.ERROR);
+                    return Observable.just(download);
+                });
     }
 
     // Get the image from the filesystem if it exists or download from network
@@ -215,9 +216,9 @@ public class DownloadManager {
         return pageObservable
                 // When the image is ready, set image path, progress (just in case) and status
                 .doOnNext(p -> {
-                    p.setImagePath(imagePath.getAbsolutePath());
-                    p.setProgress(100);
-                    p.setStatus(Page.READY);
+                    page.setImagePath(imagePath.getAbsolutePath());
+                    page.setProgress(100);
+                    page.setStatus(Page.READY);
                     download.downloadedImages++;
                 })
                 // If the download fails, mark this page as error
@@ -226,6 +227,7 @@ public class DownloadManager {
                 .onErrorResumeNext(e -> Observable.just(page));
     }
 
+    // Save image on disk
     private Observable<Page> downloadImage(Page page, Source source, File directory, String filename) {
         page.setStatus(Page.DOWNLOAD_IMAGE);
         return source.getImageProgressResponse(page)
@@ -261,12 +263,7 @@ public class DownloadManager {
 
     // Get the filename for an image given the page
     private String getImageFilename(Page page) {
-        String url;
-        try {
-            url = new URL(page.getImageUrl()).getPath();
-        } catch (MalformedURLException e) {
-            url = page.getImageUrl();
-        }
+        String url = UrlUtil.getPath(page.getImageUrl());
         return url.substring(
                 url.lastIndexOf("/") + 1,
                 url.length());
@@ -288,7 +285,11 @@ public class DownloadManager {
         // If any page has an error, the download result will be error
         for (Page page : download.pages) {
             actualProgress += page.getProgress();
-            if (page.getStatus() == Page.ERROR) status = Download.ERROR;
+            if (page.getStatus() != Page.READY) status = Download.ERROR;
+        }
+        // Ensure that the chapter folder has all the images
+        if (!isChapterDownloaded(download.directory, download.pages)) {
+            status = Download.ERROR;
         }
         download.totalProgress = actualProgress;
         download.setStatus(status);

+ 3 - 3
app/src/main/java/eu/kanade/mangafeed/data/network/NetworkHelper.java

@@ -42,7 +42,7 @@ public final class NetworkHelper {
             } catch (Throwable e) {
                 return Observable.error(e);
             }
-        }).retry(3);
+        }).retry(2);
     }
 
     public Observable<String> mapResponseToString(final Response response) {
@@ -72,7 +72,7 @@ public final class NetworkHelper {
             } catch (Throwable e) {
                 return Observable.error(e);
             }
-        }).retry(3);
+        }).retry(2);
     }
 
     public Observable<Response> getProgressResponse(final String url, final Headers headers, final ProgressListener listener) {
@@ -96,7 +96,7 @@ public final class NetworkHelper {
             } catch (Throwable e) {
                 return Observable.error(e);
             }
-        }).retry(3);
+        }).retry(2);
     }
 
     public CookieStore getCookies() {

+ 5 - 2
app/src/main/java/eu/kanade/mangafeed/data/source/base/Source.java

@@ -8,6 +8,7 @@ import com.squareup.okhttp.Response;
 
 import org.jsoup.Jsoup;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -153,8 +154,10 @@ public abstract class Source extends BaseSource {
         page.setStatus(Page.DOWNLOAD_IMAGE);
         return getImageProgressResponse(page)
                 .flatMap(resp -> {
-                    if (!cacheManager.putImageToDiskCache(page.getImageUrl(), resp)) {
-                        throw new IllegalStateException("Unable to save image");
+                    try {
+                        cacheManager.putImageToDiskCache(page.getImageUrl(), resp);
+                    } catch (IOException e) {
+                        return Observable.error(e);
                     }
                     return Observable.just(page);
                 });

+ 1 - 1
app/src/main/java/eu/kanade/mangafeed/data/source/model/Page.java

@@ -8,7 +8,7 @@ public class Page implements ProgressListener {
     private int pageNumber;
     private String url;
     private String imageUrl;
-    private String imagePath;
+    private transient String imagePath;
     private transient volatile int status;
     private transient volatile int progress;
 

+ 3 - 3
app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java

@@ -130,13 +130,13 @@ public final class DiskUtils {
         try {
             bufferedSink = Okio.buffer(Okio.sink(writeFile));
             bufferedSink.writeAll(bufferedSource);
-            bufferedSink.close();
         } catch (Exception e) {
+            writeFile.delete();
+            throw new IOException("Unable to save image");
+        } finally {
             if (bufferedSink != null) {
                 bufferedSink.close();
             }
-            writeFile.delete();
-            throw new IOException("Failed saving image");
         }
 
         return writeFile;