Hold a wake lock until downloads are finished

This commit is contained in:
inorichi 2015-11-07 22:10:08 +01:00
parent 0f372ba069
commit a130506514
2 changed files with 67 additions and 17 deletions

View File

@ -28,6 +28,7 @@ import eu.kanade.mangafeed.util.DiskUtils;
import eu.kanade.mangafeed.util.DynamicConcurrentMergeOperator;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import rx.subjects.BehaviorSubject;
import rx.subjects.PublishSubject;
@ -46,7 +47,8 @@ public class DownloadManager {
private Subscription threadsNumberSubscription;
private DownloadQueue queue;
private transient boolean isQueuePaused;
private volatile boolean isQueuePaused;
private volatile boolean isRunning;
public static final String PAGE_LIST_FILE = "index.json";
@ -54,9 +56,12 @@ public class DownloadManager {
this.context = context;
this.sourceManager = sourceManager;
this.preferences = preferences;
this.gson = new Gson();
gson = new Gson();
queue = new DownloadQueue();
downloadsQueueSubject = PublishSubject.create();
threadsNumber = BehaviorSubject.create();
}
public void initializeSubscriptions() {
@ -66,9 +71,6 @@ public class DownloadManager {
if (threadsNumberSubscription != null && !threadsNumberSubscription.isUnsubscribed())
threadsNumberSubscription.unsubscribe();
downloadsQueueSubject = PublishSubject.create();
threadsNumber = BehaviorSubject.create();
threadsNumberSubscription = preferences.getDownloadTheadsObservable()
.filter(n -> !isQueuePaused)
.doOnNext(n -> isQueuePaused = (n == 0))
@ -78,11 +80,19 @@ public class DownloadManager {
.observeOn(Schedulers.newThread())
.lift(new DynamicConcurrentMergeOperator<>(this::downloadChapter, threadsNumber))
.onBackpressureBuffer()
.subscribe(page -> {},
e -> Timber.e(e.fillInStackTrace(), e.getMessage()));
.observeOn(AndroidSchedulers.mainThread())
.subscribe(finished -> {
if (finished) {
DownloadService.stop(context);
}
}, e -> Timber.e(e.fillInStackTrace(), e.getMessage()));
isRunning = true;
}
public void destroySubscriptions() {
isRunning = false;
if (downloadsSubscription != null && !downloadsSubscription.isUnsubscribed()) {
downloadsSubscription.unsubscribe();
downloadsSubscription = null;
@ -104,6 +114,7 @@ public class DownloadManager {
if (!isChapterDownloaded(download)) {
queue.add(download);
if (isRunning) downloadsQueueSubject.onNext(download);
}
}
}
@ -139,7 +150,7 @@ public class DownloadManager {
}
// Download the entire chapter
private Observable<Page> downloadChapter(Download download) {
private Observable<Boolean> downloadChapter(Download download) {
try {
DiskUtils.createDirectory(download.directory);
} catch (IOException e) {
@ -164,7 +175,9 @@ public class DownloadManager {
// Start downloading images, consider we can have downloaded images already
.concatMap(page -> getDownloadedImage(page, download.source, download.directory))
// Do after download completes
.doOnCompleted(() -> onDownloadCompleted(download));
.doOnCompleted(() -> onDownloadCompleted(download))
.toList()
.flatMap(pages -> Observable.just(areAllDownloadsFinished()));
}
// Get downloaded image if exists, otherwise download it with the method below
@ -229,9 +242,6 @@ public class DownloadManager {
private void onDownloadCompleted(final Download download) {
checkDownloadIsSuccessful(download);
savePageList(download);
if (areAllDownloadsFinished()) {
DownloadService.stop(context);
}
}
private void checkDownloadIsSuccessful(final Download download) {
@ -336,20 +346,27 @@ public class DownloadManager {
threadsNumber.onNext(0);
}
public void startDownloads() {
public boolean startDownloads() {
boolean hasPendingDownloads = false;
if (downloadsSubscription == null || threadsNumberSubscription == null)
initializeSubscriptions();
for (Download download : queue.get()) {
if (download.getStatus() != Download.DOWNLOADED) {
download.setStatus(Download.QUEUE);
if (!hasPendingDownloads) hasPendingDownloads = true;
downloadsQueueSubject.onNext(download);
}
}
return hasPendingDownloads;
}
public void stopDownloads() {
destroySubscriptions();
}
public boolean isRunning() {
return isRunning;
}
}

View File

@ -6,6 +6,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.IBinder;
import android.os.PowerManager;
import javax.inject.Inject;
@ -22,6 +23,7 @@ public class DownloadService extends Service {
@Inject DownloadManager downloadManager;
private PowerManager.WakeLock wakeLock;
private Subscription networkChangeSubscription;
public static void start(Context context) {
@ -37,11 +39,10 @@ public class DownloadService extends Service {
super.onCreate();
App.get(this).getComponent().inject(this);
// An initial event will be fired when subscribed.
// This will cause the following download events to start or wait for a connection
listenNetworkChanges();
createWakeLock();
EventBus.getDefault().registerSticky(this);
listenNetworkChanges();
}
@Override
@ -54,6 +55,7 @@ public class DownloadService extends Service {
EventBus.getDefault().unregister(this);
networkChangeSubscription.unsubscribe();
downloadManager.destroySubscriptions();
destroyWakeLock();
super.onDestroy();
}
@ -66,6 +68,8 @@ public class DownloadService extends Service {
public void onEvent(DownloadChaptersEvent event) {
EventBus.getDefault().removeStickyEvent(event);
downloadManager.onDownloadChaptersEvent(event);
if (downloadManager.isRunning())
acquireWakeLock();
}
private void listenNetworkChanges() {
@ -73,11 +77,40 @@ public class DownloadService extends Service {
networkChangeSubscription = ContentObservable.fromBroadcast(this, intentFilter)
.subscribe(state -> {
if (NetworkUtil.isNetworkConnected(this)) {
downloadManager.startDownloads();
// If there are no remaining downloads, destroy the service
if (!downloadManager.startDownloads())
stopSelf();
else
acquireWakeLock();
} else {
downloadManager.stopDownloads();
releaseWakeLock();
}
});
}
private void createWakeLock() {
wakeLock = ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "DownloadService:WakeLock");
}
private void destroyWakeLock() {
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
wakeLock = null;
}
}
public void acquireWakeLock() {
if (wakeLock != null && !wakeLock.isHeld()) {
wakeLock.acquire();
}
}
public void releaseWakeLock() {
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
}
}
}