mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-24 14:31:52 +01:00
Convert app updater to foreground service
This commit is contained in:
parent
f1a9434d10
commit
d20c7f41af
@ -38,7 +38,7 @@ internal class UpdaterNotifier(private val context: Context) {
|
||||
*
|
||||
* @param title tile of notification.
|
||||
*/
|
||||
fun onDownloadStarted(title: String) {
|
||||
fun onDownloadStarted(title: String): NotificationCompat.Builder {
|
||||
with(notification) {
|
||||
setContentTitle(title)
|
||||
setContentText(context.getString(R.string.downloading))
|
||||
@ -46,6 +46,7 @@ internal class UpdaterNotifier(private val context: Context) {
|
||||
setOngoing(true)
|
||||
}
|
||||
notification.show()
|
||||
return notification
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,36 +1,86 @@
|
||||
package eu.kanade.tachiyomi.data.updater
|
||||
|
||||
import android.app.IntentService
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.os.PowerManager
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.ProgressListener
|
||||
import eu.kanade.tachiyomi.network.await
|
||||
import eu.kanade.tachiyomi.network.newCallWithProgress
|
||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import eu.kanade.tachiyomi.util.storage.saveTo
|
||||
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
|
||||
class UpdaterService : IntentService(UpdaterService::class.java.name) {
|
||||
class UpdaterService : Service() {
|
||||
|
||||
private val network: NetworkHelper by injectLazy()
|
||||
|
||||
/**
|
||||
* Notifier for the updater state and progress.
|
||||
* Wake lock that will be held until the service is destroyed.
|
||||
*/
|
||||
private val notifier by lazy { UpdaterNotifier(this) }
|
||||
private lateinit var wakeLock: PowerManager.WakeLock
|
||||
|
||||
override fun onHandleIntent(intent: Intent?) {
|
||||
if (intent == null) return
|
||||
private lateinit var notifier: UpdaterNotifier
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
notifier = UpdaterNotifier(this)
|
||||
|
||||
startForeground(Notifications.ID_UPDATER, notifier.onDownloadStarted(getString(R.string.app_name)).build())
|
||||
|
||||
wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, "${javaClass.name}:WakeLock"
|
||||
)
|
||||
wakeLock.acquire()
|
||||
}
|
||||
|
||||
/**
|
||||
* This method needs to be implemented, but it's not used/needed.
|
||||
*/
|
||||
override fun onBind(intent: Intent): IBinder? = null
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
if (intent == null) return START_NOT_STICKY
|
||||
|
||||
val url = intent.getStringExtra(EXTRA_DOWNLOAD_URL) ?: return START_NOT_STICKY
|
||||
val title = intent.getStringExtra(EXTRA_DOWNLOAD_TITLE) ?: getString(R.string.app_name)
|
||||
val url = intent.getStringExtra(EXTRA_DOWNLOAD_URL) ?: return
|
||||
downloadApk(title, url)
|
||||
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
downloadApk(title, url)
|
||||
}
|
||||
|
||||
stopSelf(startId)
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
override fun stopService(name: Intent?): Boolean {
|
||||
destroyJob()
|
||||
return super.stopService(name)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
destroyJob()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun destroyJob() {
|
||||
if (wakeLock.isHeld) {
|
||||
wakeLock.release()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,12 +88,11 @@ class UpdaterService : IntentService(UpdaterService::class.java.name) {
|
||||
*
|
||||
* @param url url location of file
|
||||
*/
|
||||
private fun downloadApk(title: String, url: String) {
|
||||
private suspend fun downloadApk(title: String, url: String) {
|
||||
// Show notification download starting.
|
||||
notifier.onDownloadStarted(title)
|
||||
|
||||
val progressListener = object : ProgressListener {
|
||||
|
||||
// Progress of the download
|
||||
var savedProgress = 0
|
||||
|
||||
@ -63,7 +112,7 @@ class UpdaterService : IntentService(UpdaterService::class.java.name) {
|
||||
|
||||
try {
|
||||
// Download the new update.
|
||||
val response = network.client.newCallWithProgress(GET(url), progressListener).execute()
|
||||
val response = network.client.newCallWithProgress(GET(url), progressListener).await()
|
||||
|
||||
// File where the apk will be saved.
|
||||
val apkFile = File(externalCacheDir, "update.apk")
|
||||
@ -82,27 +131,36 @@ class UpdaterService : IntentService(UpdaterService::class.java.name) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Download url.
|
||||
*/
|
||||
|
||||
internal const val EXTRA_DOWNLOAD_URL = "${BuildConfig.APPLICATION_ID}.UpdaterService.DOWNLOAD_URL"
|
||||
internal const val EXTRA_DOWNLOAD_TITLE = "${BuildConfig.APPLICATION_ID}.UpdaterService.DOWNLOAD_TITLE"
|
||||
|
||||
/**
|
||||
* Download title
|
||||
* Returns the status of the service.
|
||||
*
|
||||
* @param context the application context.
|
||||
* @return true if the service is running, false otherwise.
|
||||
*/
|
||||
internal const val EXTRA_DOWNLOAD_TITLE = "${BuildConfig.APPLICATION_ID}.UpdaterService.DOWNLOAD_TITLE"
|
||||
private fun isRunning(context: Context): Boolean =
|
||||
context.isServiceRunning(UpdaterService::class.java)
|
||||
|
||||
/**
|
||||
* Downloads a new update and let the user install the new version from a notification.
|
||||
* @param context the application context.
|
||||
* @param url the url to the new update.
|
||||
*/
|
||||
fun downloadUpdate(context: Context, url: String, title: String = context.getString(R.string.app_name)) {
|
||||
val intent = Intent(context, UpdaterService::class.java).apply {
|
||||
putExtra(EXTRA_DOWNLOAD_TITLE, title)
|
||||
putExtra(EXTRA_DOWNLOAD_URL, url)
|
||||
fun start(context: Context, url: String, title: String = context.getString(R.string.app_name)) {
|
||||
if (!isRunning(context)) {
|
||||
val intent = Intent(context, UpdaterService::class.java).apply {
|
||||
putExtra(EXTRA_DOWNLOAD_TITLE, title)
|
||||
putExtra(EXTRA_DOWNLOAD_URL, url)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
context.startService(intent)
|
||||
} else {
|
||||
context.startForegroundService(intent)
|
||||
}
|
||||
}
|
||||
context.startService(intent)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
|
||||
class SettingsAboutController : SettingsController() {
|
||||
class AboutController : SettingsController() {
|
||||
|
||||
/**
|
||||
* Checks for new releases
|
||||
@ -172,7 +172,7 @@ class SettingsAboutController : SettingsController() {
|
||||
if (appContext != null) {
|
||||
// Start download
|
||||
val url = args.getString(URL_KEY) ?: ""
|
||||
UpdaterService.downloadUpdate(appContext, url)
|
||||
UpdaterService.start(appContext, url)
|
||||
}
|
||||
}
|
||||
.negativeButton(R.string.ignore)
|
@ -75,7 +75,7 @@ class SettingsMainController : SettingsController() {
|
||||
iconRes = R.drawable.ic_info_black_24dp
|
||||
iconTint = tintColor
|
||||
titleRes = R.string.about
|
||||
onClick { navigateTo(SettingsAboutController()) }
|
||||
onClick { navigateTo(AboutController()) }
|
||||
}
|
||||
}
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
|
Loading…
Reference in New Issue
Block a user