diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateService.kt index 8b000f0cf0..ea1307e26f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreateService.kt @@ -70,11 +70,11 @@ class BackupCreateService : Service() { override fun onCreate() { super.onCreate() + notifier = BackupNotifier(this) + wakeLock = acquireWakeLock(javaClass.name) startForeground(Notifications.ID_BACKUP_PROGRESS, notifier.showBackupProgress().build()) - - wakeLock = acquireWakeLock(javaClass.name) } override fun stopService(name: Intent?): Boolean { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt index c016764d0a..59ca6316ed 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt @@ -124,11 +124,11 @@ class BackupRestoreService : Service() { override fun onCreate() { super.onCreate() + notifier = BackupNotifier(this) + wakeLock = acquireWakeLock(javaClass.name) startForeground(Notifications.ID_RESTORE_PROGRESS, notifier.showRestoreProgress().build()) - - wakeLock = acquireWakeLock(javaClass.name) } override fun stopService(name: Intent?): Boolean { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt new file mode 100644 index 0000000000..adcceeb066 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -0,0 +1,268 @@ +package eu.kanade.tachiyomi.data.library + +import android.app.Notification +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat +import com.bumptech.glide.Glide +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.database.models.Chapter +import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.glide.toMangaThumbnail +import eu.kanade.tachiyomi.data.notification.NotificationReceiver +import eu.kanade.tachiyomi.data.notification.Notifications +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.ui.main.MainActivity +import eu.kanade.tachiyomi.util.lang.chop +import eu.kanade.tachiyomi.util.system.notification +import eu.kanade.tachiyomi.util.system.notificationBuilder +import eu.kanade.tachiyomi.util.system.notificationManager +import java.text.DecimalFormat +import java.text.DecimalFormatSymbols +import uy.kohesive.injekt.injectLazy + +class LibraryUpdateNotifier(private val context: Context) { + + private val preferences: PreferencesHelper by injectLazy() + + /** + * Pending intent of action that cancels the library update + */ + private val cancelIntent by lazy { + NotificationReceiver.cancelLibraryUpdatePendingBroadcast(context) + } + + /** + * Bitmap of the app for notifications. + */ + private val notificationBitmap by lazy { + BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher) + } + + /** + * Cached progress notification to avoid creating a lot. + */ + val progressNotificationBuilder by lazy { + context.notificationBuilder(Notifications.CHANNEL_LIBRARY) { + setContentTitle(context.getString(R.string.app_name)) + setSmallIcon(R.drawable.ic_refresh_24dp) + setLargeIcon(notificationBitmap) + setOngoing(true) + setOnlyAlertOnce(true) + addAction(R.drawable.ic_close_24dp, context.getString(android.R.string.cancel), cancelIntent) + } + } + + /** + * Shows the notification containing the currently updating manga and the progress. + * + * @param manga the manga that's being updated. + * @param current the current progress. + * @param total the total progress. + */ + fun showProgressNotification(manga: Manga, current: Int, total: Int) { + val title = if (preferences.hideNotificationContent()) { + context.getString(R.string.notification_check_updates) + } else { + manga.title + } + + context.notificationManager.notify( + Notifications.ID_LIBRARY_PROGRESS, + progressNotificationBuilder + .setContentTitle(title) + .setProgress(total, current, false) + .build() + ) + } + + /** + * Shows the notification containing the result of the update done by the service. + * + * @param updates a list of manga with new updates. + */ + fun showUpdateNotifications(updates: List>>) { + if (updates.isEmpty()) { + return + } + + NotificationManagerCompat.from(context).apply { + // Parent group notification + notify( + Notifications.ID_NEW_CHAPTERS, + context.notification(Notifications.CHANNEL_NEW_CHAPTERS) { + setContentTitle(context.getString(R.string.notification_new_chapters)) + if (updates.size == 1 && !preferences.hideNotificationContent()) { + setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN)) + } else { + setContentText(context.resources.getQuantityString(R.plurals.notification_new_chapters_summary, updates.size, updates.size)) + + if (!preferences.hideNotificationContent()) { + setStyle( + NotificationCompat.BigTextStyle().bigText( + updates.joinToString("\n") { + it.first.title.chop(NOTIF_TITLE_MAX_LEN) + } + ) + ) + } + } + + setSmallIcon(R.drawable.ic_tachi) + setLargeIcon(notificationBitmap) + + setGroup(Notifications.GROUP_NEW_CHAPTERS) + setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) + setGroupSummary(true) + priority = NotificationCompat.PRIORITY_HIGH + + setContentIntent(getNotificationIntent()) + setAutoCancel(true) + } + ) + + // Per-manga notification + if (!preferences.hideNotificationContent()) { + updates.forEach { + val (manga, chapters) = it + notify(manga.id.hashCode(), createNewChaptersNotification(manga, chapters)) + } + } + } + } + + private fun createNewChaptersNotification(manga: Manga, chapters: Array): Notification { + return context.notification(Notifications.CHANNEL_NEW_CHAPTERS) { + setContentTitle(manga.title) + + val description = getNewChaptersDescription(chapters) + setContentText(description) + setStyle(NotificationCompat.BigTextStyle().bigText(description)) + + setSmallIcon(R.drawable.ic_tachi) + + val icon = getMangaIcon(manga) + if (icon != null) { + setLargeIcon(icon) + } + + setGroup(Notifications.GROUP_NEW_CHAPTERS) + setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) + priority = NotificationCompat.PRIORITY_HIGH + + // Open first chapter on tap + setContentIntent(NotificationReceiver.openChapterPendingActivity(context, manga, chapters.first())) + setAutoCancel(true) + + // Mark chapters as read action + addAction( + R.drawable.ic_glasses_black_24dp, context.getString(R.string.action_mark_as_read), + NotificationReceiver.markAsReadPendingBroadcast( + context, + manga, chapters, Notifications.ID_NEW_CHAPTERS + ) + ) + // View chapters action + addAction( + R.drawable.ic_book_24dp, context.getString(R.string.action_view_chapters), + NotificationReceiver.openChapterPendingActivity( + context, + manga, Notifications.ID_NEW_CHAPTERS + ) + ) + } + } + + /** + * Cancels the progress notification. + */ + fun cancelProgressNotification() { + context.notificationManager.cancel(Notifications.ID_LIBRARY_PROGRESS) + } + + private fun getMangaIcon(manga: Manga): Bitmap? { + return try { + Glide.with(context) + .asBitmap() + .load(manga.toMangaThumbnail()) + .dontTransform() + .centerCrop() + .circleCrop() + .override( + NOTIF_ICON_SIZE, + NOTIF_ICON_SIZE + ) + .submit() + .get() + } catch (e: Exception) { + null + } + } + + private fun getNewChaptersDescription(chapters: Array): String { + val formatter = DecimalFormat( + "#.###", + DecimalFormatSymbols() + .apply { decimalSeparator = '.' } + ) + + val displayableChapterNumbers = chapters + .filter { it.isRecognizedNumber } + .sortedBy { it.chapter_number } + .map { formatter.format(it.chapter_number) } + .toSet() + + return when (displayableChapterNumbers.size) { + // No sensible chapter numbers to show (i.e. no chapters have parsed chapter number) + 0 -> { + // "1 new chapter" or "5 new chapters" + context.resources.getQuantityString(R.plurals.notification_chapters_generic, chapters.size, chapters.size) + } + // Only 1 chapter has a parsed chapter number + 1 -> { + val remaining = chapters.size - displayableChapterNumbers.size + if (remaining == 0) { + // "Chapter 2.5" + context.resources.getString(R.string.notification_chapters_single, displayableChapterNumbers.first()) + } else { + // "Chapter 2.5 and 10 more" + context.resources.getString(R.string.notification_chapters_single_and_more, displayableChapterNumbers.first(), remaining) + } + } + // Everything else (i.e. multiple parsed chapter numbers) + else -> { + val shouldTruncate = displayableChapterNumbers.size > NOTIF_MAX_CHAPTERS + if (shouldTruncate) { + // "Chapters 1, 2.5, 3, 4, 5 and 10 more" + val remaining = displayableChapterNumbers.size - NOTIF_MAX_CHAPTERS + val joinedChapterNumbers = displayableChapterNumbers.take(NOTIF_MAX_CHAPTERS).joinToString(", ") + context.resources.getQuantityString(R.plurals.notification_chapters_multiple_and_more, remaining, joinedChapterNumbers, remaining) + } else { + // "Chapters 1, 2.5, 3" + context.resources.getString(R.string.notification_chapters_multiple, displayableChapterNumbers.joinToString(", ")) + } + } + } + } + + /** + * Returns an intent to open the main activity. + */ + private fun getNotificationIntent(): PendingIntent { + val intent = Intent(context, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP + action = MainActivity.SHORTCUT_RECENTLY_UPDATED + } + return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) + } + + companion object { + private const val NOTIF_MAX_CHAPTERS = 5 + private const val NOTIF_TITLE_MAX_LEN = 45 + private const val NOTIF_ICON_SIZE = 192 + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index c3ffec7632..5c76accfe9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -1,20 +1,11 @@ package eu.kanade.tachiyomi.data.library -import android.app.Notification -import android.app.PendingIntent import android.app.Service import android.content.Context import android.content.Intent -import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.os.Build import android.os.IBinder import android.os.PowerManager -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationCompat.GROUP_ALERT_SUMMARY -import androidx.core.app.NotificationManagerCompat -import com.bumptech.glide.Glide -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Category @@ -23,26 +14,17 @@ import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadService -import eu.kanade.tachiyomi.data.glide.toMangaThumbnail import eu.kanade.tachiyomi.data.library.LibraryUpdateRanker.rankingScheme import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start -import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource -import eu.kanade.tachiyomi.util.lang.chop import eu.kanade.tachiyomi.util.prepUpdateCover import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.isServiceRunning -import eu.kanade.tachiyomi.util.system.notification -import eu.kanade.tachiyomi.util.system.notificationBuilder -import eu.kanade.tachiyomi.util.system.notificationManager -import java.text.DecimalFormat -import java.text.DecimalFormatSymbols import java.util.ArrayList import java.util.concurrent.atomic.AtomicInteger import rx.Observable @@ -74,39 +56,13 @@ class LibraryUpdateService( */ private lateinit var wakeLock: PowerManager.WakeLock + private lateinit var notifier: LibraryUpdateNotifier + /** * Subscription where the update is done. */ private var subscription: Subscription? = null - /** - * Pending intent of action that cancels the library update - */ - private val cancelIntent by lazy { - NotificationReceiver.cancelLibraryUpdatePendingBroadcast(this) - } - - /** - * Bitmap of the app for notifications. - */ - private val notificationBitmap by lazy { - BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher) - } - - /** - * Cached progress notification to avoid creating a lot. - */ - private val progressNotificationBuilder by lazy { - notificationBuilder(Notifications.CHANNEL_LIBRARY) { - setContentTitle(getString(R.string.app_name)) - setSmallIcon(R.drawable.ic_refresh_24dp) - setLargeIcon(notificationBitmap) - setOngoing(true) - setOnlyAlertOnce(true) - addAction(R.drawable.ic_close_24dp, getString(android.R.string.cancel), cancelIntent) - } - } - /** * Defines what should be updated within a service execution. */ @@ -128,10 +84,6 @@ class LibraryUpdateService( */ const val KEY_TARGET = "target" - private const val NOTIF_MAX_CHAPTERS = 5 - private const val NOTIF_TITLE_MAX_LEN = 45 - private const val NOTIF_ICON_SIZE = 192 - /** * Returns the status of the service. * @@ -186,9 +138,10 @@ class LibraryUpdateService( override fun onCreate() { super.onCreate() - startForeground(Notifications.ID_LIBRARY_PROGRESS, progressNotificationBuilder.build()) - + notifier = LibraryUpdateNotifier(this) wakeLock = acquireWakeLock(javaClass.name) + + startForeground(Notifications.ID_LIBRARY_PROGRESS, notifier.progressNotificationBuilder.build()) } /** @@ -316,7 +269,7 @@ class LibraryUpdateService( { bySource -> bySource // Notify manga that will update. - .doOnNext { showProgressNotification(it, count.andIncrement, mangaToUpdate.size) } + .doOnNext { notifier.showProgressNotification(it, count.andIncrement, mangaToUpdate.size) } .concatMap { manga -> updateManga(manga) // If there's any error, return empty update and continue. @@ -358,7 +311,7 @@ class LibraryUpdateService( // Notify result of the overall update. .doOnCompleted { if (newUpdates.isNotEmpty()) { - showUpdateNotifications(newUpdates) + notifier.showUpdateNotifications(newUpdates) if (downloadNew && hasDownloads) { DownloadService.start(this) } @@ -368,7 +321,7 @@ class LibraryUpdateService( Timber.e("Failed updating: ${failedUpdates.map { it.title }}") } - cancelProgressNotification() + notifier.cancelProgressNotification() } .map { manga -> manga.first } } @@ -415,14 +368,14 @@ class LibraryUpdateService( var count = 0 return Observable.from(mangaToUpdate) - .doOnNext { showProgressNotification(it, count++, mangaToUpdate.size) } + .doOnNext { notifier.showProgressNotification(it, count++, mangaToUpdate.size) } .map { manga -> manga.prepUpdateCover(coverCache) db.insertManga(manga).executeAsBlocking() manga } .doOnCompleted { - cancelProgressNotification() + notifier.cancelProgressNotification() } } @@ -439,7 +392,7 @@ class LibraryUpdateService( // Emit each manga and update it sequentially. return Observable.from(mangaToUpdate) // Notify manga that will update. - .doOnNext { showProgressNotification(it, count++, mangaToUpdate.size) } + .doOnNext { notifier.showProgressNotification(it, count++, mangaToUpdate.size) } // Update the tracking details. .concatMap { manga -> val tracks = db.getTracks(manga).executeAsBlocking() @@ -458,207 +411,7 @@ class LibraryUpdateService( .map { manga } } .doOnCompleted { - cancelProgressNotification() + notifier.cancelProgressNotification() } } - - /** - * Shows the notification containing the currently updating manga and the progress. - * - * @param manga the manga that's being updated. - * @param current the current progress. - * @param total the total progress. - */ - private fun showProgressNotification(manga: Manga, current: Int, total: Int) { - val title = if (preferences.hideNotificationContent()) { - getString(R.string.notification_check_updates) - } else { - manga.title - } - - notificationManager.notify( - Notifications.ID_LIBRARY_PROGRESS, - progressNotificationBuilder - .setContentTitle(title) - .setProgress(total, current, false) - .build() - ) - } - - /** - * Shows the notification containing the result of the update done by the service. - * - * @param updates a list of manga with new updates. - */ - private fun showUpdateNotifications(updates: List>>) { - if (updates.isEmpty()) { - return - } - - NotificationManagerCompat.from(this).apply { - // Parent group notification - notify( - Notifications.ID_NEW_CHAPTERS, - notification(Notifications.CHANNEL_NEW_CHAPTERS) { - setContentTitle(getString(R.string.notification_new_chapters)) - if (updates.size == 1 && !preferences.hideNotificationContent()) { - setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN)) - } else { - setContentText(resources.getQuantityString(R.plurals.notification_new_chapters_summary, updates.size, updates.size)) - - if (!preferences.hideNotificationContent()) { - setStyle( - NotificationCompat.BigTextStyle().bigText( - updates.joinToString("\n") { - it.first.title.chop(NOTIF_TITLE_MAX_LEN) - } - ) - ) - } - } - - setSmallIcon(R.drawable.ic_tachi) - setLargeIcon(notificationBitmap) - - setGroup(Notifications.GROUP_NEW_CHAPTERS) - setGroupAlertBehavior(GROUP_ALERT_SUMMARY) - setGroupSummary(true) - priority = NotificationCompat.PRIORITY_HIGH - - setContentIntent(getNotificationIntent()) - setAutoCancel(true) - } - ) - - // Per-manga notification - if (!preferences.hideNotificationContent()) { - updates.forEach { - val (manga, chapters) = it - notify(manga.id.hashCode(), createNewChaptersNotification(manga, chapters)) - } - } - } - } - - private fun createNewChaptersNotification(manga: Manga, chapters: Array): Notification { - return notification(Notifications.CHANNEL_NEW_CHAPTERS) { - setContentTitle(manga.title) - - val description = getNewChaptersDescription(chapters) - setContentText(description) - setStyle(NotificationCompat.BigTextStyle().bigText(description)) - - setSmallIcon(R.drawable.ic_tachi) - - val icon = getMangaIcon(manga) - if (icon != null) { - setLargeIcon(icon) - } - - setGroup(Notifications.GROUP_NEW_CHAPTERS) - setGroupAlertBehavior(GROUP_ALERT_SUMMARY) - priority = NotificationCompat.PRIORITY_HIGH - - // Open first chapter on tap - setContentIntent(NotificationReceiver.openChapterPendingActivity(this@LibraryUpdateService, manga, chapters.first())) - setAutoCancel(true) - - // Mark chapters as read action - addAction( - R.drawable.ic_glasses_black_24dp, getString(R.string.action_mark_as_read), - NotificationReceiver.markAsReadPendingBroadcast( - this@LibraryUpdateService, - manga, chapters, Notifications.ID_NEW_CHAPTERS - ) - ) - // View chapters action - addAction( - R.drawable.ic_book_24dp, getString(R.string.action_view_chapters), - NotificationReceiver.openChapterPendingActivity( - this@LibraryUpdateService, - manga, Notifications.ID_NEW_CHAPTERS - ) - ) - } - } - - /** - * Cancels the progress notification. - */ - private fun cancelProgressNotification() { - notificationManager.cancel(Notifications.ID_LIBRARY_PROGRESS) - } - - private fun getMangaIcon(manga: Manga): Bitmap? { - return try { - Glide.with(this) - .asBitmap() - .load(manga.toMangaThumbnail()) - .dontTransform() - .centerCrop() - .circleCrop() - .override(NOTIF_ICON_SIZE, NOTIF_ICON_SIZE) - .submit() - .get() - } catch (e: Exception) { - null - } - } - - private fun getNewChaptersDescription(chapters: Array): String { - val formatter = DecimalFormat( - "#.###", - DecimalFormatSymbols() - .apply { decimalSeparator = '.' } - ) - - val displayableChapterNumbers = chapters - .filter { it.isRecognizedNumber } - .sortedBy { it.chapter_number } - .map { formatter.format(it.chapter_number) } - .toSet() - - return when (displayableChapterNumbers.size) { - // No sensible chapter numbers to show (i.e. no chapters have parsed chapter number) - 0 -> { - // "1 new chapter" or "5 new chapters" - resources.getQuantityString(R.plurals.notification_chapters_generic, chapters.size, chapters.size) - } - // Only 1 chapter has a parsed chapter number - 1 -> { - val remaining = chapters.size - displayableChapterNumbers.size - if (remaining == 0) { - // "Chapter 2.5" - resources.getString(R.string.notification_chapters_single, displayableChapterNumbers.first()) - } else { - // "Chapter 2.5 and 10 more" - resources.getString(R.string.notification_chapters_single_and_more, displayableChapterNumbers.first(), remaining) - } - } - // Everything else (i.e. multiple parsed chapter numbers) - else -> { - val shouldTruncate = displayableChapterNumbers.size > NOTIF_MAX_CHAPTERS - if (shouldTruncate) { - // "Chapters 1, 2.5, 3, 4, 5 and 10 more" - val remaining = displayableChapterNumbers.size - NOTIF_MAX_CHAPTERS - val joinedChapterNumbers = displayableChapterNumbers.take(NOTIF_MAX_CHAPTERS).joinToString(", ") - resources.getQuantityString(R.plurals.notification_chapters_multiple_and_more, remaining, joinedChapterNumbers, remaining) - } else { - // "Chapters 1, 2.5, 3" - resources.getString(R.string.notification_chapters_multiple, displayableChapterNumbers.joinToString(", ")) - } - } - } - } - - /** - * Returns an intent to open the main activity. - */ - private fun getNotificationIntent(): PendingIntent { - val intent = Intent(this, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP - action = MainActivity.SHORTCUT_RECENTLY_UPDATED - } - return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterService.kt index 23e0154388..74df3c35c6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterService.kt @@ -37,11 +37,11 @@ class UpdaterService : Service() { override fun onCreate() { super.onCreate() + notifier = UpdaterNotifier(this) + wakeLock = acquireWakeLock(javaClass.name) startForeground(Notifications.ID_UPDATER, notifier.onDownloadStarted().build()) - - wakeLock = acquireWakeLock(javaClass.name) } /**