100% functional manager self upgrade

Fix #2929
This commit is contained in:
topjohnwu 2020-08-28 04:46:05 -07:00
parent 7e133b0cf4
commit 01efe7a4ea
17 changed files with 102 additions and 123 deletions

View File

@ -64,14 +64,6 @@ object Const {
const val ETAG_KEY = "ETag" const val ETAG_KEY = "ETag"
// intents // intents
const val OPEN_SECTION = "section" const val OPEN_SECTION = "section"
const val OPEN_SETTINGS = "settings"
const val INTENT_SET_APP = "app_json"
const val FLASH_INSTALLER = "installer"
const val FLASH_ACTION = "action"
const val FLASH_DATA = "additional_data"
const val DISMISS_ID = "dismiss_id"
const val BROADCAST_MANAGER_UPDATE = "manager_update"
const val BROADCAST_REBOOT = "reboot"
} }
object Value { object Value {

View File

@ -3,13 +3,8 @@ package com.topjohnwu.magisk.core
import android.content.ContextWrapper import android.content.ContextWrapper
import android.content.Intent import android.content.Intent
import com.topjohnwu.magisk.core.base.BaseReceiver import com.topjohnwu.magisk.core.base.BaseReceiver
import com.topjohnwu.magisk.core.download.Action
import com.topjohnwu.magisk.core.download.DownloadService
import com.topjohnwu.magisk.core.download.Subject
import com.topjohnwu.magisk.core.magiskdb.PolicyDao import com.topjohnwu.magisk.core.magiskdb.PolicyDao
import com.topjohnwu.magisk.core.model.ManagerJson
import com.topjohnwu.magisk.core.su.SuCallbackHandler import com.topjohnwu.magisk.core.su.SuCallbackHandler
import com.topjohnwu.magisk.ktx.reboot
import com.topjohnwu.magisk.view.Shortcuts import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
@ -46,15 +41,6 @@ open class GeneralReceiver : BaseReceiver() {
Shell.su("magiskhide --rm $pkg").submit() Shell.su("magiskhide --rm $pkg").submit()
} }
Intent.ACTION_LOCALE_CHANGED -> Shortcuts.setupDynamic(context) Intent.ACTION_LOCALE_CHANGED -> Shortcuts.setupDynamic(context)
Const.Key.BROADCAST_MANAGER_UPDATE -> {
intent.getParcelableExtra<ManagerJson>(Const.Key.INTENT_SET_APP)?.let {
Info.remote = Info.remote.copy(app = it)
}
DownloadService(context) {
subject = Subject.Manager(Action.APK.Upgrade)
}
}
Const.Key.BROADCAST_REBOOT -> reboot()
} }
} }
} }

View File

@ -13,7 +13,6 @@ import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import com.topjohnwu.magisk.core.utils.ProgressInputStream import com.topjohnwu.magisk.core.utils.ProgressInputStream
import com.topjohnwu.magisk.data.network.GithubRawServices import com.topjohnwu.magisk.data.network.GithubRawServices
import com.topjohnwu.magisk.ktx.withStreams import com.topjohnwu.magisk.ktx.withStreams
import com.topjohnwu.magisk.ktx.writeTo
import com.topjohnwu.magisk.view.Notifications import com.topjohnwu.magisk.view.Notifications
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -29,7 +28,7 @@ import java.util.*
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.random.Random.Default.nextInt import kotlin.random.Random.Default.nextInt
abstract class BaseDownloadService : BaseService(), KoinComponent { abstract class BaseDownloader : BaseService(), KoinComponent {
private val hasNotifications get() = notifications.isNotEmpty() private val hasNotifications get() = notifications.isNotEmpty()
private val notifications = Collections.synchronizedMap(HashMap<Int, Notification.Builder>()) private val notifications = Collections.synchronizedMap(HashMap<Int, Notification.Builder>())
@ -41,8 +40,8 @@ abstract class BaseDownloadService : BaseService(), KoinComponent {
override fun onBind(intent: Intent?): IBinder? = null override fun onBind(intent: Intent?): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
intent?.getParcelableExtra<Subject>(ARG_URL)?.let { subject -> intent.getParcelableExtra<Subject>(ACTION_KEY)?.let { subject ->
update(subject.notifyID()) update(subject.notifyID())
coroutineScope.launch { coroutineScope.launch {
try { try {
@ -76,8 +75,11 @@ abstract class BaseDownloadService : BaseService(), KoinComponent {
when (this) { when (this) {
is Subject.Module -> // Download and process on-the-fly is Subject.Module -> // Download and process on-the-fly
stream.toModule(file, service.fetchInstaller().byteStream()) stream.toModule(file, service.fetchInstaller().byteStream())
else -> else -> {
withStreams(stream, file.outputStream()) { it, out -> it.copyTo(out) } withStreams(stream, file.outputStream()) { it, out -> it.copyTo(out) }
if (this is Subject.Manager)
handleAPK(this)
}
} }
} }
val newId = notifyFinish(this) val newId = notifyFinish(this)
@ -124,6 +126,7 @@ abstract class BaseDownloadService : BaseService(), KoinComponent {
private fun notifyFinish(subject: Subject) = lastNotify(subject.notifyID()) { private fun notifyFinish(subject: Subject) = lastNotify(subject.notifyID()) {
broadcast(1f, subject) broadcast(1f, subject)
it.setIntent(subject) it.setIntent(subject)
.setContentTitle(subject.title)
.setContentText(getString(R.string.download_complete)) .setContentText(getString(R.string.download_complete))
.setSmallIcon(android.R.drawable.stat_sys_download_done) .setSmallIcon(android.R.drawable.stat_sys_download_done)
.setProgress(0, 0, false) .setProgress(0, 0, false)
@ -152,16 +155,15 @@ abstract class BaseDownloadService : BaseService(), KoinComponent {
return newId return newId
} }
private fun remove(id: Int) = notifications.remove(id)?.also { protected fun remove(id: Int) = notifications.remove(id)
updateForeground() ?.also { updateForeground(); cancel(id) }
cancel(id) ?: { cancel(id); null }()
}
private fun notify(id: Int, notification: Notification) { private fun notify(id: Int, notification: Notification) {
Notifications.mgr.notify(id, notification) Notifications.mgr.notify(id, notification)
} }
protected fun cancel(id: Int) { private fun cancel(id: Int) {
Notifications.mgr.cancel(id) Notifications.mgr.cancel(id)
} }
@ -178,13 +180,12 @@ abstract class BaseDownloadService : BaseService(), KoinComponent {
protected abstract suspend fun onFinish(subject: Subject, id: Int) protected abstract suspend fun onFinish(subject: Subject, id: Int)
protected abstract fun Notification.Builder.setIntent(subject: Subject) protected abstract fun Notification.Builder.setIntent(subject: Subject): Notification.Builder
: Notification.Builder
// --- // ---
companion object : KoinComponent { companion object : KoinComponent {
const val ARG_URL = "arg_url" const val ACTION_KEY = "download_action"
private val progressBroadcast = MutableLiveData<Pair<Float, Subject>>() private val progressBroadcast = MutableLiveData<Pair<Float, Subject>>()

View File

@ -17,7 +17,7 @@ import com.topjohnwu.magisk.utils.APKInstall
import kotlin.random.Random.Default.nextInt import kotlin.random.Random.Default.nextInt
@SuppressLint("Registered") @SuppressLint("Registered")
open class DownloadService : BaseDownloadService() { open class DownloadService : BaseDownloader() {
private val context get() = this private val context get() = this
@ -30,7 +30,7 @@ open class DownloadService : BaseDownloadService() {
private suspend fun Magisk.onFinish(id: Int) = when (val action = action) { private suspend fun Magisk.onFinish(id: Int) = when (val action = action) {
Uninstall -> FlashFragment.uninstall(file, id) Uninstall -> FlashFragment.uninstall(file, id)
EnvFix -> { EnvFix -> {
cancel(id) remove(id)
EnvFixTask(file).exec() EnvFixTask(file).exec()
Unit Unit
} }
@ -44,9 +44,9 @@ open class DownloadService : BaseDownloadService() {
else -> Unit else -> Unit
} }
private suspend fun Manager.onFinish(id: Int) { private fun Manager.onFinish(id: Int) {
handleAPK(this) remove(id)
cancel(id) APKInstall.install(context, file.toFile())
} }
// --- Customize finish notification // --- Customize finish notification
@ -85,24 +85,29 @@ open class DownloadService : BaseDownloadService() {
// --- // ---
class Builder {
lateinit var subject: Subject
}
companion object { companion object {
inline operator fun invoke(context: Context, argBuilder: Builder.() -> Unit) { private fun intent(context: Context, subject: Subject) =
val app = context.applicationContext context.intent<DownloadService>().putExtra(ACTION_KEY, subject)
val builder = Builder().apply(argBuilder)
val intent = app.intent<DownloadService>().putExtra(ARG_URL, builder.subject)
if (Build.VERSION.SDK_INT >= 26) { fun pendingIntent(context: Context, subject: Subject): PendingIntent {
app.startForegroundService(intent) return if (Build.VERSION.SDK_INT >= 26) {
PendingIntent.getForegroundService(context, nextInt(),
intent(context, subject), PendingIntent.FLAG_UPDATE_CURRENT)
} else { } else {
app.startService(intent) PendingIntent.getService(context, nextInt(),
intent(context, subject), PendingIntent.FLAG_UPDATE_CURRENT)
}
}
operator fun invoke(context: Context, subject: Subject) {
val app = context.applicationContext
if (Build.VERSION.SDK_INT >= 26) {
app.startForegroundService(intent(app, subject))
} else {
app.startService(intent(app, subject))
}
} }
} }
} }
}

View File

@ -1,5 +1,6 @@
package com.topjohnwu.magisk.core.download package com.topjohnwu.magisk.core.download
import android.content.Context
import androidx.core.net.toFile import androidx.core.net.toFile
import com.topjohnwu.magisk.BuildConfig import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.DynAPK import com.topjohnwu.magisk.DynAPK
@ -12,49 +13,48 @@ import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.utils.PatchAPK import com.topjohnwu.magisk.core.utils.PatchAPK
import com.topjohnwu.magisk.ktx.relaunchApp import com.topjohnwu.magisk.ktx.relaunchApp
import com.topjohnwu.magisk.ktx.writeTo import com.topjohnwu.magisk.ktx.writeTo
import com.topjohnwu.magisk.utils.APKInstall
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import java.io.File import java.io.File
private fun DownloadService.patch(apk: File, id: Int) { private fun Context.patch(apk: File) {
if (packageName == BuildConfig.APPLICATION_ID)
return
update(id) {
it.setProgress(0, 0, true)
.setProgress(0, 0, true)
.setContentTitle(getString(R.string.hide_manager_title))
.setContentText("")
}
val patched = File(apk.parent, "patched.apk") val patched = File(apk.parent, "patched.apk")
PatchAPK.patch(apk.path, patched.path, packageName, applicationInfo.nonLocalizedLabel) PatchAPK.patch(apk.path, patched.path, packageName, applicationInfo.nonLocalizedLabel)
apk.delete() apk.delete()
patched.renameTo(apk) patched.renameTo(apk)
} }
private suspend fun DownloadService.upgrade(apk: File, id: Int) { private fun BaseDownloader.notifyHide(id: Int) {
update(id) {
it.setProgress(0, 0, true)
.setContentTitle(getString(R.string.hide_manager_title))
.setContentText("")
}
}
private suspend fun BaseDownloader.upgrade(subject: Subject.Manager) {
val apk = subject.file.toFile()
val id = subject.notifyID()
if (isRunningAsStub) { if (isRunningAsStub) {
// Move to upgrade location // Move to upgrade location
apk.copyTo(DynAPK.update(this), overwrite = true) apk.copyTo(DynAPK.update(this), overwrite = true)
apk.delete() apk.delete()
if (Info.stubChk.version < Info.remote.stub.versionCode) { if (Info.stubChk.version < subject.stub.versionCode) {
// We also want to upgrade stub notifyHide(id)
service.fetchFile(Info.remote.stub.link).byteStream().use { // Also upgrade stub
it.writeTo(apk) service.fetchFile(subject.stub.link).byteStream().use { it.writeTo(apk) }
} patch(apk)
patch(apk, id)
} else { } else {
// Simply relaunch the app // Simply relaunch the app
stopSelf() stopSelf()
relaunchApp(this) relaunchApp(this)
} }
} else { } else if (packageName != BuildConfig.APPLICATION_ID) {
patch(apk, id) notifyHide(id)
patch(apk)
} }
APKInstall.install(this, apk)
} }
private fun DownloadService.restore(apk: File, id: Int) { private fun BaseDownloader.restore(apk: File, id: Int) {
update(id) { update(id) {
it.setProgress(0, 0, true) it.setProgress(0, 0, true)
.setProgress(0, 0, true) .setProgress(0, 0, true)
@ -65,8 +65,8 @@ private fun DownloadService.restore(apk: File, id: Int) {
Shell.su("pm install $apk && pm uninstall $packageName").exec() Shell.su("pm install $apk && pm uninstall $packageName").exec()
} }
suspend fun DownloadService.handleAPK(subject: Subject.Manager) = suspend fun BaseDownloader.handleAPK(subject: Subject.Manager) =
when (subject.action) { when (subject.action) {
is Upgrade -> upgrade(subject.file.toFile(), subject.notifyID()) is Upgrade -> upgrade(subject)
is Restore -> restore(subject.file.toFile(), subject.notifyID()) is Restore -> restore(subject.file.toFile(), subject.notifyID())
} }

View File

@ -7,13 +7,16 @@ import androidx.core.net.toUri
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.model.MagiskJson import com.topjohnwu.magisk.core.model.MagiskJson
import com.topjohnwu.magisk.core.model.ManagerJson import com.topjohnwu.magisk.core.model.ManagerJson
import com.topjohnwu.magisk.core.model.StubJson
import com.topjohnwu.magisk.core.model.module.Repo import com.topjohnwu.magisk.core.model.module.Repo
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.ktx.cachedFile import com.topjohnwu.magisk.ktx.cachedFile
import com.topjohnwu.magisk.ktx.get import com.topjohnwu.magisk.ktx.get
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import kotlinx.android.parcel.IgnoredOnParcel import kotlinx.android.parcel.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
private fun cachedFile(name: String) = get<Context>().cachedFile(name).apply { delete() }.toUri()
sealed class Subject : Parcelable { sealed class Subject : Parcelable {
abstract val url: String abstract val url: String
@ -37,21 +40,20 @@ sealed class Subject : Parcelable {
@Parcelize @Parcelize
class Manager( class Manager(
override val action: Action.APK override val action: Action.APK,
private val app: ManagerJson = Info.remote.app,
val stub: StubJson = Info.remote.stub
) : Subject() { ) : Subject() {
@IgnoredOnParcel
val manager: ManagerJson = Info.remote.app
override val title: String override val title: String
get() = "MagiskManager-${manager.version}(${manager.versionCode})" get() = "MagiskManager-${app.version}(${app.versionCode})"
override val url: String override val url: String
get() = manager.link get() = app.link
@IgnoredOnParcel @IgnoredOnParcel
override val file by lazy { override val file by lazy {
get<Context>().cachedFile("manager.apk").toUri() cachedFile("manager.apk")
} }
} }
@ -69,7 +71,7 @@ sealed class Subject : Parcelable {
@IgnoredOnParcel @IgnoredOnParcel
override val file by lazy { override val file by lazy {
get<Context>().cachedFile("magisk.zip").toUri() cachedFile("magisk.zip")
} }
} }
@ -81,7 +83,7 @@ sealed class Subject : Parcelable {
@IgnoredOnParcel @IgnoredOnParcel
override val file by lazy { override val file by lazy {
get<Context>().cachedFile(title).toUri() cachedFile(title)
} }
} }

View File

@ -35,8 +35,9 @@ data class ManagerJson(
val note: String = "" val note: String = ""
) : Parcelable ) : Parcelable
@Parcelize
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class StubJson( data class StubJson(
val versionCode: Int = -1, val versionCode: Int = -1,
val link: String = "" val link: String = ""
) ) : Parcelable

View File

@ -31,7 +31,7 @@ class EnvFixDialog : DialogEvent() {
lbm.unregisterReceiver(this) lbm.unregisterReceiver(this)
} }
}, IntentFilter(DISMISS)) }, IntentFilter(DISMISS))
DownloadService(dialog.context) { subject = Magisk(EnvFix) } DownloadService(dialog.context, Magisk(EnvFix))
} }
} }
.applyButton(MagiskDialog.ButtonType.NEGATIVE) { .applyButton(MagiskDialog.ButtonType.NEGATIVE) {

View File

@ -25,7 +25,7 @@ class ManagerInstallDialog : DialogEvent() {
applyButton(MagiskDialog.ButtonType.POSITIVE) { applyButton(MagiskDialog.ButtonType.POSITIVE) {
titleRes = R.string.install titleRes = R.string.install
onClick { DownloadService(context) { this.subject = subject } } onClick { DownloadService(context, subject) }
} }
if (Info.remote.app.note.isEmpty()) return if (Info.remote.app.note.isEmpty()) return

View File

@ -12,9 +12,10 @@ class ModuleInstallDialog(private val item: Repo) : DialogEvent() {
override fun build(dialog: MagiskDialog) { override fun build(dialog: MagiskDialog) {
with(dialog) { with(dialog) {
fun download(install: Boolean) = DownloadService(context) { fun download(install: Boolean) {
val config = if (install) Action.Flash.Primary else Action.Download val config = if (install) Action.Flash.Primary else Action.Download
subject = Subject.Module(item, config) val subject = Subject.Module(item, config)
DownloadService(context, subject)
} }
applyTitle(context.getString(R.string.repo_install_title, item.name)) applyTitle(context.getString(R.string.repo_install_title, item.name))

View File

@ -47,9 +47,7 @@ class UninstallDialog : DialogEvent() {
} }
private fun completeUninstall() { private fun completeUninstall() {
DownloadService(dialog.context) { DownloadService(dialog.context, Subject.Magisk(Action.Uninstall))
subject = Subject.Magisk(Action.Uninstall)
}
} }
} }

View File

@ -4,7 +4,7 @@ import android.os.Bundle
import android.view.* import android.view.*
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIFragment import com.topjohnwu.magisk.arch.BaseUIFragment
import com.topjohnwu.magisk.core.download.BaseDownloadService import com.topjohnwu.magisk.core.download.BaseDownloader
import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding
import com.topjohnwu.magisk.events.RebootEvent import com.topjohnwu.magisk.events.RebootEvent
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
@ -19,7 +19,7 @@ class HomeFragment : BaseUIFragment<HomeViewModel, FragmentHomeMd2Binding>() {
super.onStart() super.onStart()
activity.title = resources.getString(R.string.section_home) activity.title = resources.getString(R.string.section_home)
setHasOptionsMenu(true) setHasOptionsMenu(true)
BaseDownloadService.observeProgress(this, viewModel::onProgressUpdate) BaseDownloader.observeProgress(this, viewModel::onProgressUpdate)
} }
override fun onCreateView( override fun onCreateView(

View File

@ -4,7 +4,7 @@ import android.content.Intent
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIFragment import com.topjohnwu.magisk.arch.BaseUIFragment
import com.topjohnwu.magisk.core.download.BaseDownloadService import com.topjohnwu.magisk.core.download.BaseDownloader
import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding
import com.topjohnwu.magisk.events.RequestFileEvent import com.topjohnwu.magisk.events.RequestFileEvent
import com.topjohnwu.magisk.ktx.coroutineScope import com.topjohnwu.magisk.ktx.coroutineScope
@ -26,7 +26,7 @@ class InstallFragment : BaseUIFragment<InstallViewModel, FragmentInstallMd2Bindi
// Allow markwon to run in viewmodel scope // Allow markwon to run in viewmodel scope
binding.releaseNotes.coroutineScope = viewModel.viewModelScope binding.releaseNotes.coroutineScope = viewModel.viewModelScope
BaseDownloadService.observeProgress(this, viewModel::onProgressUpdate) BaseDownloader.observeProgress(this, viewModel::onProgressUpdate)
} }
} }

View File

@ -78,17 +78,16 @@ class InstallViewModel(
step = nextStep step = nextStep
} }
fun install() = DownloadService(get()) { fun install() =
subject = Subject.Magisk(resolveConfiguration()) DownloadService(get(), Subject.Magisk(resolveAction())).also { state = State.LOADING }
}.also { state = State.LOADING }
// --- // ---
private fun resolveConfiguration() = when (method) { private fun resolveAction() = when (method) {
R.id.method_download -> Action.Download R.id.method_download -> Action.Download
R.id.method_patch -> Action.Patch(data!!) R.id.method_patch -> Action.Patch(data!!)
R.id.method_direct -> Action.Flash.Primary R.id.method_direct -> Action.Flash.Primary
R.id.method_inactive_slot -> Action.Flash.Secondary R.id.method_inactive_slot -> Action.Flash.Secondary
else -> throw IllegalArgumentException("Unknown value") else -> error("Unknown value")
} }
} }

View File

@ -12,7 +12,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIFragment import com.topjohnwu.magisk.arch.BaseUIFragment
import com.topjohnwu.magisk.arch.ReselectionTarget import com.topjohnwu.magisk.arch.ReselectionTarget
import com.topjohnwu.magisk.arch.ViewEvent import com.topjohnwu.magisk.arch.ViewEvent
import com.topjohnwu.magisk.core.download.BaseDownloadService import com.topjohnwu.magisk.core.download.BaseDownloader
import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
import com.topjohnwu.magisk.events.InstallExternalModuleEvent import com.topjohnwu.magisk.events.InstallExternalModuleEvent
import com.topjohnwu.magisk.ktx.hideKeyboard import com.topjohnwu.magisk.ktx.hideKeyboard
@ -51,7 +51,7 @@ class ModuleFragment : BaseUIFragment<ModuleViewModel, FragmentModuleMd2Binding>
super.onStart() super.onStart()
setHasOptionsMenu(true) setHasOptionsMenu(true)
activity.title = resources.getString(R.string.modules) activity.title = resources.getString(R.string.modules)
BaseDownloadService.observeProgress(this, viewModel::onProgressUpdate) BaseDownloader.observeProgress(this, viewModel::onProgressUpdate)
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View File

@ -145,9 +145,7 @@ class SettingsViewModel(
} }
private fun restoreManager() { private fun restoreManager() {
DownloadService(get()) { DownloadService(get(), Subject.Manager(Action.APK.Restore))
subject = Subject.Manager(Action.APK.Restore)
}
} }
} }

View File

@ -10,9 +10,15 @@ import androidx.core.app.TaskStackBuilder
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.toIcon import androidx.core.graphics.drawable.toIcon
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.* import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Const.ID.PROGRESS_NOTIFICATION_CHANNEL import com.topjohnwu.magisk.core.Const.ID.PROGRESS_NOTIFICATION_CHANNEL
import com.topjohnwu.magisk.core.Const.ID.UPDATE_NOTIFICATION_CHANNEL import com.topjohnwu.magisk.core.Const.ID.UPDATE_NOTIFICATION_CHANNEL
import com.topjohnwu.magisk.core.SplashActivity
import com.topjohnwu.magisk.core.cmp
import com.topjohnwu.magisk.core.download.Action
import com.topjohnwu.magisk.core.download.DownloadService
import com.topjohnwu.magisk.core.download.Subject
import com.topjohnwu.magisk.core.intent
import com.topjohnwu.magisk.ktx.get import com.topjohnwu.magisk.ktx.get
import com.topjohnwu.magisk.ktx.getBitmap import com.topjohnwu.magisk.ktx.getBitmap
@ -52,12 +58,9 @@ object Notifications {
stackBuilder.addParentStack(SplashActivity::class.java.cmp(context.packageName)) stackBuilder.addParentStack(SplashActivity::class.java.cmp(context.packageName))
stackBuilder.addNextIntent(intent) stackBuilder.addNextIntent(intent)
val pendingIntent = stackBuilder.getPendingIntent( val pendingIntent = stackBuilder.getPendingIntent(
Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, PendingIntent.FLAG_UPDATE_CURRENT)
PendingIntent.FLAG_UPDATE_CURRENT)
val builder = updateBuilder( val builder = updateBuilder(context)
context
)
.setContentTitle(context.getString(R.string.magisk_update_title)) .setContentTitle(context.getString(R.string.magisk_update_title))
.setContentText(context.getString(R.string.manager_download_install)) .setContentText(context.getString(R.string.manager_download_install))
.setAutoCancel(true) .setAutoCancel(true)
@ -67,20 +70,13 @@ object Notifications {
} }
fun managerUpdate(context: Context) { fun managerUpdate(context: Context) {
val intent = context.intent<GeneralReceiver>() val intent = DownloadService.pendingIntent(context, Subject.Manager(Action.APK.Upgrade))
.setAction(Const.Key.BROADCAST_MANAGER_UPDATE)
.putExtra(Const.Key.INTENT_SET_APP, Info.remote.app)
val pendingIntent = PendingIntent.getBroadcast(context, val builder = updateBuilder(context)
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val builder = updateBuilder(
context
)
.setContentTitle(context.getString(R.string.manager_update_title)) .setContentTitle(context.getString(R.string.manager_update_title))
.setContentText(context.getString(R.string.manager_download_install)) .setContentText(context.getString(R.string.manager_download_install))
.setAutoCancel(true) .setAutoCancel(true)
.setContentIntent(pendingIntent) .setContentIntent(intent)
mgr.notify(Const.ID.APK_UPDATE_NOTIFICATION_ID, builder.build()) mgr.notify(Const.ID.APK_UPDATE_NOTIFICATION_ID, builder.build())
} }