Remove local broadcast receiver to prevent race conditions (#1123)

* Remove local broadcast receiver to prevent run exceptions.
Added option to set tile for extension update.
This commit is contained in:
Bram van de Kerkhof 2017-12-11 20:01:28 +01:00 committed by GitHub
parent 6a63ce992a
commit 8994b42760
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 215 additions and 317 deletions

View File

@ -86,7 +86,7 @@
android:exported="false" /> android:exported="false" />
<service <service
android:name=".data.updater.UpdateDownloaderService" android:name=".data.updater.UpdaterService"
android:exported="false" /> android:exported="false" />
<service <service

View File

@ -8,7 +8,7 @@ import com.evernote.android.job.JobManager
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.updater.UpdateCheckerJob import eu.kanade.tachiyomi.data.updater.UpdaterJob
import eu.kanade.tachiyomi.util.LocaleHelper import eu.kanade.tachiyomi.util.LocaleHelper
import org.acra.ACRA import org.acra.ACRA
import org.acra.annotation.ReportsCrashes import org.acra.annotation.ReportsCrashes
@ -60,7 +60,7 @@ open class App : Application() {
JobManager.create(this).addJobCreator { tag -> JobManager.create(this).addJobCreator { tag ->
when (tag) { when (tag) {
LibraryUpdateJob.TAG -> LibraryUpdateJob() LibraryUpdateJob.TAG -> LibraryUpdateJob()
UpdateCheckerJob.TAG -> UpdateCheckerJob() UpdaterJob.TAG -> UpdaterJob()
BackupCreatorJob.TAG -> BackupCreatorJob() BackupCreatorJob.TAG -> BackupCreatorJob()
else -> null else -> null
} }

View File

@ -3,7 +3,7 @@ package eu.kanade.tachiyomi
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.updater.UpdateCheckerJob import eu.kanade.tachiyomi.data.updater.UpdaterJob
import java.io.File import java.io.File
object Migrations { object Migrations {
@ -25,7 +25,7 @@ object Migrations {
if (oldVersion < 14) { if (oldVersion < 14) {
// Restore jobs after upgrading to evernote's job scheduler. // Restore jobs after upgrading to evernote's job scheduler.
if (BuildConfig.INCLUDE_UPDATER && preferences.automaticUpdates()) { if (BuildConfig.INCLUDE_UPDATER && preferences.automaticUpdates()) {
UpdateCheckerJob.setupTask() UpdaterJob.setupTask()
} }
LibraryUpdateJob.setupTask() LibraryUpdateJob.setupTask()
} }

View File

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.notification
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.getUriCompat import eu.kanade.tachiyomi.util.getUriCompat
import java.io.File import java.io.File
@ -43,11 +44,10 @@ object NotificationHandler {
* Returns [PendingIntent] that prompts user with apk install intent * Returns [PendingIntent] that prompts user with apk install intent
* *
* @param context context * @param context context
* @param file file of apk that is installed * @param uri uri of apk that is installed
*/ */
fun installApkPendingActivity(context: Context, file: File): PendingIntent { fun installApkPendingActivity(context: Context, uri: Uri): PendingIntent {
val intent = Intent(Intent.ACTION_VIEW).apply { val intent = Intent(Intent.ACTION_VIEW).apply {
val uri = file.getUriCompat(context)
setDataAndType(uri, "application/vnd.android.package-archive") setDataAndType(uri, "application/vnd.android.package-archive")
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
} }

View File

@ -11,8 +11,8 @@ import com.google.gson.annotations.SerializedName
* @param assets assets of latest release. * @param assets assets of latest release.
*/ */
class GithubRelease(@SerializedName("tag_name") val version: String, class GithubRelease(@SerializedName("tag_name") val version: String,
@SerializedName("body") val changeLog: String, @SerializedName("body") val changeLog: String,
@SerializedName("assets") val assets: List<Assets>) { @SerializedName("assets") private val assets: List<Assets>) {
/** /**
* Get download link of latest release from the assets. * Get download link of latest release from the assets.

View File

@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.updater
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import rx.Observable import rx.Observable
class GithubUpdateChecker() { class GithubUpdateChecker {
private val service: GithubService = GithubService.create() private val service: GithubService = GithubService.create()

View File

@ -3,5 +3,5 @@ package eu.kanade.tachiyomi.data.updater
sealed class GithubUpdateResult { sealed class GithubUpdateResult {
class NewUpdate(val release: GithubRelease): GithubUpdateResult() class NewUpdate(val release: GithubRelease): GithubUpdateResult()
class NoNewUpdate(): GithubUpdateResult() class NoNewUpdate : GithubUpdateResult()
} }

View File

@ -1,147 +0,0 @@
package eu.kanade.tachiyomi.data.updater
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.support.v4.app.NotificationCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.NotificationHandler
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.notificationManager
import java.io.File
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
/**
* Local [BroadcastReceiver] that runs on UI thread
* Notification calls from [UpdateDownloaderService] should be made from here.
*/
internal class UpdateDownloaderReceiver(val context: Context) : BroadcastReceiver() {
companion object {
private const val NAME = "UpdateDownloaderReceiver"
// Called to show initial notification.
internal const val NOTIFICATION_UPDATER_INITIAL = "$ID.$NAME.UPDATER_INITIAL"
// Called to show progress notification.
internal const val NOTIFICATION_UPDATER_PROGRESS = "$ID.$NAME.UPDATER_PROGRESS"
// Called to show install notification.
internal const val NOTIFICATION_UPDATER_INSTALL = "$ID.$NAME.UPDATER_INSTALL"
// Called to show error notification
internal const val NOTIFICATION_UPDATER_ERROR = "$ID.$NAME.UPDATER_ERROR"
// Value containing action of BroadcastReceiver
internal const val EXTRA_ACTION = "$ID.$NAME.ACTION"
// Value containing progress
internal const val EXTRA_PROGRESS = "$ID.$NAME.PROGRESS"
// Value containing apk path
internal const val EXTRA_APK_PATH = "$ID.$NAME.APK_PATH"
// Value containing apk url
internal const val EXTRA_APK_URL = "$ID.$NAME.APK_URL"
}
/**
* Notification shown to user
*/
private val notification = NotificationCompat.Builder(context, Notifications.CHANNEL_COMMON)
override fun onReceive(context: Context, intent: Intent) {
when (intent.getStringExtra(EXTRA_ACTION)) {
NOTIFICATION_UPDATER_INITIAL -> basicNotification()
NOTIFICATION_UPDATER_PROGRESS -> updateProgress(intent.getIntExtra(EXTRA_PROGRESS, 0))
NOTIFICATION_UPDATER_INSTALL -> installNotification(intent.getStringExtra(EXTRA_APK_PATH))
NOTIFICATION_UPDATER_ERROR -> errorNotification(intent.getStringExtra(EXTRA_APK_URL))
}
}
/**
* Called to show basic notification
*/
private fun basicNotification() {
// Create notification
with(notification) {
setContentTitle(context.getString(R.string.app_name))
setContentText(context.getString(R.string.update_check_notification_download_in_progress))
setSmallIcon(android.R.drawable.stat_sys_download)
setOngoing(true)
}
notification.show()
}
/**
* Called to show progress notification
*
* @param progress progress of download
*/
private fun updateProgress(progress: Int) {
with(notification) {
setProgress(100, progress, false)
setOnlyAlertOnce(true)
}
notification.show()
}
/**
* Called to show install notification
*
* @param path path of file
*/
private fun installNotification(path: String) {
// Prompt the user to install the new update.
with(notification) {
setContentText(context.getString(R.string.update_check_notification_download_complete))
setSmallIcon(android.R.drawable.stat_sys_download_done)
setOnlyAlertOnce(false)
setProgress(0, 0, false)
// Install action
setContentIntent(NotificationHandler.installApkPendingActivity(context, File(path)))
addAction(R.drawable.ic_system_update_grey_24dp_img,
context.getString(R.string.action_install),
NotificationHandler.installApkPendingActivity(context, File(path)))
// Cancel action
addAction(R.drawable.ic_clear_grey_24dp_img,
context.getString(R.string.action_cancel),
NotificationReceiver.dismissNotificationPendingBroadcast(context, Notifications.ID_UPDATER))
}
notification.show()
}
/**
* Called to show error notification
*
* @param url url of apk
*/
private fun errorNotification(url: String) {
// Prompt the user to retry the download.
with(notification) {
setContentText(context.getString(R.string.update_check_notification_download_error))
setSmallIcon(android.R.drawable.stat_sys_warning)
setOnlyAlertOnce(false)
setProgress(0, 0, false)
// Retry action
addAction(R.drawable.ic_refresh_grey_24dp_img,
context.getString(R.string.action_retry),
UpdateDownloaderService.downloadApkPendingService(context, url))
// Cancel action
addAction(R.drawable.ic_clear_grey_24dp_img,
context.getString(R.string.action_cancel),
NotificationReceiver.dismissNotificationPendingBroadcast(context, Notifications.ID_UPDATER))
}
notification.show()
}
/**
* Shows a notification from this builder.
*
* @param id the id of the notification.
*/
private fun NotificationCompat.Builder.show(id: Int = Notifications.ID_UPDATER) {
context.notificationManager.notify(id, build())
}
}

View File

@ -1,67 +1,67 @@
package eu.kanade.tachiyomi.data.updater package eu.kanade.tachiyomi.data.updater
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Intent import android.content.Intent
import android.support.v4.app.NotificationCompat import android.support.v4.app.NotificationCompat
import com.evernote.android.job.Job import com.evernote.android.job.Job
import com.evernote.android.job.JobManager import com.evernote.android.job.JobManager
import com.evernote.android.job.JobRequest import com.evernote.android.job.JobRequest
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.notificationManager import eu.kanade.tachiyomi.util.notificationManager
class UpdateCheckerJob : Job() { class UpdaterJob : Job() {
override fun onRunJob(params: Params): Result { override fun onRunJob(params: Params): Result {
return GithubUpdateChecker() return GithubUpdateChecker()
.checkForUpdate() .checkForUpdate()
.map { result -> .map { result ->
if (result is GithubUpdateResult.NewUpdate) { if (result is GithubUpdateResult.NewUpdate) {
val url = result.release.downloadLink val url = result.release.downloadLink
val intent = Intent(context, UpdateDownloaderService::class.java).apply { val intent = Intent(context, UpdaterService::class.java).apply {
putExtra(UpdateDownloaderService.EXTRA_DOWNLOAD_URL, url) putExtra(UpdaterService.EXTRA_DOWNLOAD_URL, url)
} }
NotificationCompat.Builder(context, Notifications.CHANNEL_COMMON).update { NotificationCompat.Builder(context, Notifications.CHANNEL_COMMON).update {
setContentTitle(context.getString(R.string.app_name)) setContentTitle(context.getString(R.string.app_name))
setContentText(context.getString(R.string.update_check_notification_update_available)) setContentText(context.getString(R.string.update_check_notification_update_available))
setSmallIcon(android.R.drawable.stat_sys_download_done) setSmallIcon(android.R.drawable.stat_sys_download_done)
// Download action // Download action
addAction(android.R.drawable.stat_sys_download_done, addAction(android.R.drawable.stat_sys_download_done,
context.getString(R.string.action_download), context.getString(R.string.action_download),
PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)) PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT))
} }
} }
Job.Result.SUCCESS Job.Result.SUCCESS
} }
.onErrorReturn { Job.Result.FAILURE } .onErrorReturn { Job.Result.FAILURE }
// Sadly, the task needs to be synchronous. // Sadly, the task needs to be synchronous.
.toBlocking() .toBlocking()
.single() .single()
} }
fun NotificationCompat.Builder.update(block: NotificationCompat.Builder.() -> Unit) { fun NotificationCompat.Builder.update(block: NotificationCompat.Builder.() -> Unit) {
block() block()
context.notificationManager.notify(Notifications.ID_UPDATER, build()) context.notificationManager.notify(Notifications.ID_UPDATER, build())
} }
companion object { companion object {
const val TAG = "UpdateChecker" const val TAG = "UpdateChecker"
fun setupTask() { fun setupTask() {
JobRequest.Builder(TAG) JobRequest.Builder(TAG)
.setPeriodic(24 * 60 * 60 * 1000, 60 * 60 * 1000) .setPeriodic(24 * 60 * 60 * 1000, 60 * 60 * 1000)
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED) .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
.setRequirementsEnforced(true) .setRequirementsEnforced(true)
.setUpdateCurrent(true) .setUpdateCurrent(true)
.build() .build()
.schedule() .schedule()
} }
fun cancelTask() { fun cancelTask() {
JobManager.instance().cancelAllForTag(TAG) JobManager.instance().cancelAllForTag(TAG)
} }
} }
} }

View File

@ -0,0 +1,109 @@
package eu.kanade.tachiyomi.data.updater
import android.content.Context
import android.net.Uri
import android.support.v4.app.NotificationCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.NotificationHandler
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.notificationManager
/**
* DownloadNotifier is used to show notifications when downloading and update.
*
* @param context context of application.
*/
internal class UpdaterNotifier(private val context: Context) {
/**
* Builder to manage notifications.
*/
private val notification by lazy {
NotificationCompat.Builder(context, Notifications.CHANNEL_COMMON)
}
/**
* Call to show notification.
*
* @param id id of the notification channel.
*/
private fun NotificationCompat.Builder.show(id: Int = Notifications.ID_UPDATER) {
context.notificationManager.notify(id, build())
}
/**
* Call when apk download starts.
*
* @param title tile of notification.
*/
fun onDownloadStarted(title: String) {
with(notification) {
setContentTitle(title)
setContentText(context.getString(R.string.update_check_notification_download_in_progress))
setSmallIcon(android.R.drawable.stat_sys_download)
setOngoing(true)
}
notification.show()
}
/**
* Call when apk download progress changes.
*
* @param progress progress of download (xx%/100).
*/
fun onProgressChange(progress: Int) {
with(notification) {
setProgress(100, progress, false)
setOnlyAlertOnce(true)
}
notification.show()
}
/**
* Call when apk download is finished.
*
* @param uri path location of apk.
*/
fun onDownloadFinished(uri: Uri) {
with(notification) {
setContentText(context.getString(R.string.update_check_notification_download_complete))
setSmallIcon(android.R.drawable.stat_sys_download_done)
setOnlyAlertOnce(false)
setProgress(0, 0, false)
// Install action
setContentIntent(NotificationHandler.installApkPendingActivity(context, uri))
addAction(R.drawable.ic_system_update_grey_24dp_img,
context.getString(R.string.action_install),
NotificationHandler.installApkPendingActivity(context, uri))
// Cancel action
addAction(R.drawable.ic_clear_grey_24dp_img,
context.getString(R.string.action_cancel),
NotificationReceiver.dismissNotificationPendingBroadcast(context, Notifications.ID_UPDATER))
}
notification.show()
}
/**
* Call when apk download throws a error
*
* @param url web location of apk to download.
*/
fun onDownloadError(url: String) {
with(notification) {
setContentText(context.getString(R.string.update_check_notification_download_error))
setSmallIcon(android.R.drawable.stat_sys_warning)
setOnlyAlertOnce(false)
setProgress(0, 0, false)
// Retry action
addAction(R.drawable.ic_refresh_grey_24dp_img,
context.getString(R.string.action_retry),
UpdaterService.downloadApkPendingService(context, url))
// Cancel action
addAction(R.drawable.ic_clear_grey_24dp_img,
context.getString(R.string.action_cancel),
NotificationReceiver.dismissNotificationPendingBroadcast(context, Notifications.ID_UPDATER))
}
notification.show(Notifications.ID_UPDATER)
}
}

View File

@ -2,52 +2,37 @@ package eu.kanade.tachiyomi.data.updater
import android.app.IntentService import android.app.IntentService
import android.app.PendingIntent import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.ProgressListener import eu.kanade.tachiyomi.network.ProgressListener
import eu.kanade.tachiyomi.network.newCallWithProgress import eu.kanade.tachiyomi.network.newCallWithProgress
import eu.kanade.tachiyomi.util.registerLocalReceiver import eu.kanade.tachiyomi.util.getUriCompat
import eu.kanade.tachiyomi.util.saveTo import eu.kanade.tachiyomi.util.saveTo
import eu.kanade.tachiyomi.util.sendLocalBroadcastSync
import eu.kanade.tachiyomi.util.unregisterLocalReceiver
import timber.log.Timber import timber.log.Timber
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
class UpdateDownloaderService : IntentService(UpdateDownloaderService::class.java.name) { class UpdaterService : IntentService(UpdaterService::class.java.name) {
/** /**
* Network helper * Network helper
*/ */
private val network: NetworkHelper by injectLazy() private val network: NetworkHelper by injectLazy()
/** /**
* Local [BroadcastReceiver] that runs on UI thread * Notifier for the updater state and progress.
*/ */
private val updaterNotificationReceiver = UpdateDownloaderReceiver(this) private val notifier by lazy { UpdaterNotifier(this) }
override fun onCreate() {
super.onCreate()
// Register receiver
registerLocalReceiver(updaterNotificationReceiver, IntentFilter(INTENT_FILTER_NAME))
}
override fun onDestroy() {
// Unregister receiver
unregisterLocalReceiver(updaterNotificationReceiver)
super.onDestroy()
}
override fun onHandleIntent(intent: Intent?) { override fun onHandleIntent(intent: Intent?) {
if (intent == null) return if (intent == null) return
val title = intent.getStringExtra(EXTRA_DOWNLOAD_TITLE) ?: getString(R.string.app_name)
val url = intent.getStringExtra(EXTRA_DOWNLOAD_URL) ?: return val url = intent.getStringExtra(EXTRA_DOWNLOAD_URL) ?: return
downloadApk(url) downloadApk(title, url)
} }
/** /**
@ -55,9 +40,9 @@ class UpdateDownloaderService : IntentService(UpdateDownloaderService::class.jav
* *
* @param url url location of file * @param url url location of file
*/ */
fun downloadApk(url: String) { private fun downloadApk(title: String, url: String) {
// Show notification download starting. // Show notification download starting.
sendInitialBroadcast() notifier.onDownloadStarted(title)
val progressListener = object : ProgressListener { val progressListener = object : ProgressListener {
@ -73,7 +58,7 @@ class UpdateDownloaderService : IntentService(UpdateDownloaderService::class.jav
if (progress > savedProgress && currentTime - 200 > lastTick) { if (progress > savedProgress && currentTime - 200 > lastTick) {
savedProgress = progress savedProgress = progress
lastTick = currentTime lastTick = currentTime
sendProgressBroadcast(progress) notifier.onProgressChange(progress)
} }
} }
} }
@ -91,80 +76,32 @@ class UpdateDownloaderService : IntentService(UpdateDownloaderService::class.jav
response.close() response.close()
throw Exception("Unsuccessful response") throw Exception("Unsuccessful response")
} }
sendInstallBroadcast(apkFile.absolutePath) notifier.onDownloadFinished(apkFile.getUriCompat(this))
} catch (error: Exception) { } catch (error: Exception) {
Timber.e(error) Timber.e(error)
sendErrorBroadcast(url) notifier.onDownloadError(url)
} }
} }
/**
* Show notification download starting.
*/
private fun sendInitialBroadcast() {
val intent = Intent(INTENT_FILTER_NAME).apply {
putExtra(UpdateDownloaderReceiver.EXTRA_ACTION, UpdateDownloaderReceiver.NOTIFICATION_UPDATER_INITIAL)
}
sendLocalBroadcastSync(intent)
}
/**
* Show notification progress changed
*
* @param progress progress of download
*/
private fun sendProgressBroadcast(progress: Int) {
val intent = Intent(INTENT_FILTER_NAME).apply {
putExtra(UpdateDownloaderReceiver.EXTRA_ACTION, UpdateDownloaderReceiver.NOTIFICATION_UPDATER_PROGRESS)
putExtra(UpdateDownloaderReceiver.EXTRA_PROGRESS, progress)
}
sendLocalBroadcastSync(intent)
}
/**
* Show install notification.
*
* @param path location of file
*/
private fun sendInstallBroadcast(path: String){
val intent = Intent(INTENT_FILTER_NAME).apply {
putExtra(UpdateDownloaderReceiver.EXTRA_ACTION, UpdateDownloaderReceiver.NOTIFICATION_UPDATER_INSTALL)
putExtra(UpdateDownloaderReceiver.EXTRA_APK_PATH, path)
}
sendLocalBroadcastSync(intent)
}
/**
* Show error notification.
*
* @param url url of file
*/
private fun sendErrorBroadcast(url: String){
val intent = Intent(INTENT_FILTER_NAME).apply {
putExtra(UpdateDownloaderReceiver.EXTRA_ACTION, UpdateDownloaderReceiver.NOTIFICATION_UPDATER_ERROR)
putExtra(UpdateDownloaderReceiver.EXTRA_APK_URL, url)
}
sendLocalBroadcastSync(intent)
}
companion object { companion object {
/**
* Name of Local BroadCastReceiver.
*/
private val INTENT_FILTER_NAME = UpdateDownloaderService::class.java.name
/** /**
* Download url. * Download url.
*/ */
internal const val EXTRA_DOWNLOAD_URL = "${BuildConfig.APPLICATION_ID}.UpdateDownloaderService.DOWNLOAD_URL" internal const val EXTRA_DOWNLOAD_URL = "${BuildConfig.APPLICATION_ID}.UpdaterService.DOWNLOAD_URL"
/**
* Download title
*/
internal const val EXTRA_DOWNLOAD_TITLE = "${BuildConfig.APPLICATION_ID}.UpdaterService.DOWNLOAD_TITLE"
/** /**
* Downloads a new update and let the user install the new version from a notification. * Downloads a new update and let the user install the new version from a notification.
* @param context the application context. * @param context the application context.
* @param url the url to the new update. * @param url the url to the new update.
*/ */
fun downloadUpdate(context: Context, url: String) { fun downloadUpdate(context: Context, url: String, title: String = context.getString(R.string.app_name)) {
val intent = Intent(context, UpdateDownloaderService::class.java).apply { val intent = Intent(context, UpdaterService::class.java).apply {
putExtra(EXTRA_DOWNLOAD_TITLE, title)
putExtra(EXTRA_DOWNLOAD_URL, url) putExtra(EXTRA_DOWNLOAD_URL, url)
} }
context.startService(intent) context.startService(intent)
@ -177,7 +114,7 @@ class UpdateDownloaderService : IntentService(UpdateDownloaderService::class.jav
* @return [PendingIntent] * @return [PendingIntent]
*/ */
internal fun downloadApkPendingService(context: Context, url: String): PendingIntent { internal fun downloadApkPendingService(context: Context, url: String): PendingIntent {
val intent = Intent(context, UpdateDownloaderService::class.java).apply { val intent = Intent(context, UpdaterService::class.java).apply {
putExtra(EXTRA_DOWNLOAD_URL, url) putExtra(EXTRA_DOWNLOAD_URL, url)
} }
return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)

View File

@ -11,8 +11,8 @@ import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.updater.GithubUpdateChecker import eu.kanade.tachiyomi.data.updater.GithubUpdateChecker
import eu.kanade.tachiyomi.data.updater.GithubUpdateResult import eu.kanade.tachiyomi.data.updater.GithubUpdateResult
import eu.kanade.tachiyomi.data.updater.UpdateCheckerJob import eu.kanade.tachiyomi.data.updater.UpdaterJob
import eu.kanade.tachiyomi.data.updater.UpdateDownloaderService import eu.kanade.tachiyomi.data.updater.UpdaterService
import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.toast import eu.kanade.tachiyomi.util.toast
import rx.Subscription import rx.Subscription
@ -59,9 +59,9 @@ class SettingsAboutController : SettingsController() {
onChange { newValue -> onChange { newValue ->
val checked = newValue as Boolean val checked = newValue as Boolean
if (checked) { if (checked) {
UpdateCheckerJob.setupTask() UpdaterJob.setupTask()
} else { } else {
UpdateCheckerJob.cancelTask() UpdaterJob.cancelTask()
} }
true true
} }
@ -148,7 +148,7 @@ class SettingsAboutController : SettingsController() {
if (appContext != null) { if (appContext != null) {
// Start download // Start download
val url = args.getString(URL_KEY) val url = args.getString(URL_KEY)
UpdateDownloaderService.downloadUpdate(appContext, url) UpdaterService.downloadUpdate(appContext, url)
} }
} }
.build() .build()

View File

@ -13,9 +13,8 @@ import java.io.File
* @param context context of application * @param context context of application
*/ */
fun File.getUriCompat(context: Context): Uri { fun File.getUriCompat(context: Context): Uri {
val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", this) FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", this)
else Uri.fromFile(this) else Uri.fromFile(this)
return uri
} }