Hold a wake lock until downloads are finished
This commit is contained in:
		
							parent
							
								
									0f372ba069
								
							
						
					
					
						commit
						a130506514
					
				| @ -28,6 +28,7 @@ import eu.kanade.mangafeed.util.DiskUtils; | |||||||
| import eu.kanade.mangafeed.util.DynamicConcurrentMergeOperator; | import eu.kanade.mangafeed.util.DynamicConcurrentMergeOperator; | ||||||
| import rx.Observable; | import rx.Observable; | ||||||
| import rx.Subscription; | import rx.Subscription; | ||||||
|  | import rx.android.schedulers.AndroidSchedulers; | ||||||
| import rx.schedulers.Schedulers; | import rx.schedulers.Schedulers; | ||||||
| import rx.subjects.BehaviorSubject; | import rx.subjects.BehaviorSubject; | ||||||
| import rx.subjects.PublishSubject; | import rx.subjects.PublishSubject; | ||||||
| @ -46,7 +47,8 @@ public class DownloadManager { | |||||||
|     private Subscription threadsNumberSubscription; |     private Subscription threadsNumberSubscription; | ||||||
| 
 | 
 | ||||||
|     private DownloadQueue queue; |     private DownloadQueue queue; | ||||||
|     private transient boolean isQueuePaused; |     private volatile boolean isQueuePaused; | ||||||
|  |     private volatile boolean isRunning; | ||||||
| 
 | 
 | ||||||
|     public static final String PAGE_LIST_FILE = "index.json"; |     public static final String PAGE_LIST_FILE = "index.json"; | ||||||
| 
 | 
 | ||||||
| @ -54,9 +56,12 @@ public class DownloadManager { | |||||||
|         this.context = context; |         this.context = context; | ||||||
|         this.sourceManager = sourceManager; |         this.sourceManager = sourceManager; | ||||||
|         this.preferences = preferences; |         this.preferences = preferences; | ||||||
|         this.gson = new Gson(); |  | ||||||
| 
 | 
 | ||||||
|  |         gson = new Gson(); | ||||||
|         queue = new DownloadQueue(); |         queue = new DownloadQueue(); | ||||||
|  | 
 | ||||||
|  |         downloadsQueueSubject = PublishSubject.create(); | ||||||
|  |         threadsNumber = BehaviorSubject.create(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void initializeSubscriptions() { |     public void initializeSubscriptions() { | ||||||
| @ -66,9 +71,6 @@ public class DownloadManager { | |||||||
|         if (threadsNumberSubscription != null && !threadsNumberSubscription.isUnsubscribed()) |         if (threadsNumberSubscription != null && !threadsNumberSubscription.isUnsubscribed()) | ||||||
|             threadsNumberSubscription.unsubscribe(); |             threadsNumberSubscription.unsubscribe(); | ||||||
| 
 | 
 | ||||||
|         downloadsQueueSubject = PublishSubject.create(); |  | ||||||
|         threadsNumber = BehaviorSubject.create(); |  | ||||||
| 
 |  | ||||||
|         threadsNumberSubscription = preferences.getDownloadTheadsObservable() |         threadsNumberSubscription = preferences.getDownloadTheadsObservable() | ||||||
|                 .filter(n -> !isQueuePaused) |                 .filter(n -> !isQueuePaused) | ||||||
|                 .doOnNext(n -> isQueuePaused = (n == 0)) |                 .doOnNext(n -> isQueuePaused = (n == 0)) | ||||||
| @ -78,11 +80,19 @@ public class DownloadManager { | |||||||
|                 .observeOn(Schedulers.newThread()) |                 .observeOn(Schedulers.newThread()) | ||||||
|                 .lift(new DynamicConcurrentMergeOperator<>(this::downloadChapter, threadsNumber)) |                 .lift(new DynamicConcurrentMergeOperator<>(this::downloadChapter, threadsNumber)) | ||||||
|                 .onBackpressureBuffer() |                 .onBackpressureBuffer() | ||||||
|                 .subscribe(page -> {}, |                 .observeOn(AndroidSchedulers.mainThread()) | ||||||
|                         e -> Timber.e(e.fillInStackTrace(), e.getMessage())); |                 .subscribe(finished -> { | ||||||
|  |                     if (finished) { | ||||||
|  |                         DownloadService.stop(context); | ||||||
|  |                     } | ||||||
|  |                 }, e -> Timber.e(e.fillInStackTrace(), e.getMessage())); | ||||||
|  | 
 | ||||||
|  |         isRunning = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void destroySubscriptions() { |     public void destroySubscriptions() { | ||||||
|  |         isRunning = false; | ||||||
|  | 
 | ||||||
|         if (downloadsSubscription != null && !downloadsSubscription.isUnsubscribed()) { |         if (downloadsSubscription != null && !downloadsSubscription.isUnsubscribed()) { | ||||||
|             downloadsSubscription.unsubscribe(); |             downloadsSubscription.unsubscribe(); | ||||||
|             downloadsSubscription = null; |             downloadsSubscription = null; | ||||||
| @ -104,6 +114,7 @@ public class DownloadManager { | |||||||
| 
 | 
 | ||||||
|             if (!isChapterDownloaded(download)) { |             if (!isChapterDownloaded(download)) { | ||||||
|                 queue.add(download); |                 queue.add(download); | ||||||
|  |                 if (isRunning) downloadsQueueSubject.onNext(download); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -139,7 +150,7 @@ public class DownloadManager { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Download the entire chapter |     // Download the entire chapter | ||||||
|     private Observable<Page> downloadChapter(Download download) { |     private Observable<Boolean> downloadChapter(Download download) { | ||||||
|         try { |         try { | ||||||
|             DiskUtils.createDirectory(download.directory); |             DiskUtils.createDirectory(download.directory); | ||||||
|         } catch (IOException e) { |         } catch (IOException e) { | ||||||
| @ -164,7 +175,9 @@ public class DownloadManager { | |||||||
|                 // Start downloading images, consider we can have downloaded images already |                 // Start downloading images, consider we can have downloaded images already | ||||||
|                 .concatMap(page -> getDownloadedImage(page, download.source, download.directory)) |                 .concatMap(page -> getDownloadedImage(page, download.source, download.directory)) | ||||||
|                 // Do after download completes |                 // 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 |     // 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) { |     private void onDownloadCompleted(final Download download) { | ||||||
|         checkDownloadIsSuccessful(download); |         checkDownloadIsSuccessful(download); | ||||||
|         savePageList(download); |         savePageList(download); | ||||||
|         if (areAllDownloadsFinished()) { |  | ||||||
|             DownloadService.stop(context); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void checkDownloadIsSuccessful(final Download download) { |     private void checkDownloadIsSuccessful(final Download download) { | ||||||
| @ -336,20 +346,27 @@ public class DownloadManager { | |||||||
|         threadsNumber.onNext(0); |         threadsNumber.onNext(0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void startDownloads() { |     public boolean startDownloads() { | ||||||
|  |         boolean hasPendingDownloads = false; | ||||||
|         if (downloadsSubscription == null || threadsNumberSubscription == null) |         if (downloadsSubscription == null || threadsNumberSubscription == null) | ||||||
|             initializeSubscriptions(); |             initializeSubscriptions(); | ||||||
| 
 | 
 | ||||||
|         for (Download download : queue.get()) { |         for (Download download : queue.get()) { | ||||||
|             if (download.getStatus() != Download.DOWNLOADED) { |             if (download.getStatus() != Download.DOWNLOADED) { | ||||||
|                 download.setStatus(Download.QUEUE); |                 download.setStatus(Download.QUEUE); | ||||||
|  |                 if (!hasPendingDownloads) hasPendingDownloads = true; | ||||||
|                 downloadsQueueSubject.onNext(download); |                 downloadsQueueSubject.onNext(download); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         return hasPendingDownloads; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void stopDownloads() { |     public void stopDownloads() { | ||||||
|         destroySubscriptions(); |         destroySubscriptions(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public boolean isRunning() { | ||||||
|  |         return isRunning; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import android.content.Intent; | |||||||
| import android.content.IntentFilter; | import android.content.IntentFilter; | ||||||
| import android.net.ConnectivityManager; | import android.net.ConnectivityManager; | ||||||
| import android.os.IBinder; | import android.os.IBinder; | ||||||
|  | import android.os.PowerManager; | ||||||
| 
 | 
 | ||||||
| import javax.inject.Inject; | import javax.inject.Inject; | ||||||
| 
 | 
 | ||||||
| @ -22,6 +23,7 @@ public class DownloadService extends Service { | |||||||
| 
 | 
 | ||||||
|     @Inject DownloadManager downloadManager; |     @Inject DownloadManager downloadManager; | ||||||
| 
 | 
 | ||||||
|  |     private PowerManager.WakeLock wakeLock; | ||||||
|     private Subscription networkChangeSubscription; |     private Subscription networkChangeSubscription; | ||||||
| 
 | 
 | ||||||
|     public static void start(Context context) { |     public static void start(Context context) { | ||||||
| @ -37,11 +39,10 @@ public class DownloadService extends Service { | |||||||
|         super.onCreate(); |         super.onCreate(); | ||||||
|         App.get(this).getComponent().inject(this); |         App.get(this).getComponent().inject(this); | ||||||
| 
 | 
 | ||||||
|         // An initial event will be fired when subscribed. |         createWakeLock(); | ||||||
|         // This will cause the following download events to start or wait for a connection |  | ||||||
|         listenNetworkChanges(); |  | ||||||
| 
 | 
 | ||||||
|         EventBus.getDefault().registerSticky(this); |         EventBus.getDefault().registerSticky(this); | ||||||
|  |         listenNetworkChanges(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
| @ -54,6 +55,7 @@ public class DownloadService extends Service { | |||||||
|         EventBus.getDefault().unregister(this); |         EventBus.getDefault().unregister(this); | ||||||
|         networkChangeSubscription.unsubscribe(); |         networkChangeSubscription.unsubscribe(); | ||||||
|         downloadManager.destroySubscriptions(); |         downloadManager.destroySubscriptions(); | ||||||
|  |         destroyWakeLock(); | ||||||
|         super.onDestroy(); |         super.onDestroy(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -66,6 +68,8 @@ public class DownloadService extends Service { | |||||||
|     public void onEvent(DownloadChaptersEvent event) { |     public void onEvent(DownloadChaptersEvent event) { | ||||||
|         EventBus.getDefault().removeStickyEvent(event); |         EventBus.getDefault().removeStickyEvent(event); | ||||||
|         downloadManager.onDownloadChaptersEvent(event); |         downloadManager.onDownloadChaptersEvent(event); | ||||||
|  |         if (downloadManager.isRunning()) | ||||||
|  |             acquireWakeLock(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void listenNetworkChanges() { |     private void listenNetworkChanges() { | ||||||
| @ -73,11 +77,40 @@ public class DownloadService extends Service { | |||||||
|         networkChangeSubscription = ContentObservable.fromBroadcast(this, intentFilter) |         networkChangeSubscription = ContentObservable.fromBroadcast(this, intentFilter) | ||||||
|                 .subscribe(state -> { |                 .subscribe(state -> { | ||||||
|                     if (NetworkUtil.isNetworkConnected(this)) { |                     if (NetworkUtil.isNetworkConnected(this)) { | ||||||
|                         downloadManager.startDownloads(); |                         // If there are no remaining downloads, destroy the service | ||||||
|  |                         if (!downloadManager.startDownloads()) | ||||||
|  |                             stopSelf(); | ||||||
|  |                         else | ||||||
|  |                             acquireWakeLock(); | ||||||
|                     } else { |                     } else { | ||||||
|                         downloadManager.stopDownloads(); |                         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(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 inorichi
						inorichi