You've already forked Magisk
mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-09-06 06:36:58 +00:00
Updated flash screen so it's a fragment
The FlashActivity has been removed and all of it's functionality has been transferred to the FlashFragment. The FlashFragment needs to be however launched in a different way than the activity using the MainActivity's stub and so seemingly massive changes had to be made. Notably the RemoteFileService didn't seem to be calling Service.startForeground(), which has been crashing the application due to the system requirements, so that's been fixed.
This commit is contained in:
committed by
John Wu
parent
fc2d0246e6
commit
6907651756
@@ -1,13 +1,147 @@
|
||||
package com.topjohnwu.magisk.ui.flash
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.core.net.toUri
|
||||
import androidx.navigation.NavDeepLinkBuilder
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.ClassMap
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.databinding.FragmentFlashMd2Binding
|
||||
import com.topjohnwu.magisk.ui.MainActivity
|
||||
import com.topjohnwu.magisk.ui.base.BaseUIActivity
|
||||
import com.topjohnwu.magisk.ui.base.BaseUIFragment
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import org.koin.core.parameter.parametersOf
|
||||
import java.io.File
|
||||
import com.topjohnwu.magisk.MainDirections.Companion.actionFlashFragment as toFlash
|
||||
import com.topjohnwu.magisk.ui.flash.FlashFragmentArgs as args
|
||||
|
||||
class FlashFragment : BaseUIFragment<FlashViewModel, FragmentFlashMd2Binding>() {
|
||||
|
||||
override val layoutRes = R.layout.fragment_flash_md2
|
||||
override val viewModel by viewModel<FlashViewModel>()
|
||||
override val viewModel by viewModel<FlashViewModel> {
|
||||
parametersOf(args.fromBundle(requireArguments()))
|
||||
}
|
||||
|
||||
private var defaultOrientation = -1
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setHasOptionsMenu(true)
|
||||
activity.setTitle(R.string.flash_screen_title)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.menu_flash, menu)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return viewModel.onMenuItemClicked(item)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
defaultOrientation = activity.requestedOrientation
|
||||
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
||||
}
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
override fun onDestroyView() {
|
||||
if (defaultOrientation != -1) {
|
||||
activity.requestedOrientation = defaultOrientation
|
||||
}
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (viewModel.loading) return true
|
||||
return super.onBackPressed()
|
||||
}
|
||||
|
||||
override fun onPreBind(binding: FragmentFlashMd2Binding) = Unit
|
||||
|
||||
companion object {
|
||||
|
||||
private fun createIntent(context: Context, args: args): PendingIntent {
|
||||
return NavDeepLinkBuilder(context)
|
||||
.setGraph(R.navigation.main)
|
||||
.setComponentName(ClassMap[MainActivity::class.java] as Class<out Activity>)
|
||||
.setDestination(R.id.flashFragment)
|
||||
.setArguments(args.toBundle())
|
||||
.createPendingIntent()
|
||||
}
|
||||
|
||||
private fun flashType(isSecondSlot: Boolean) =
|
||||
if (isSecondSlot) Const.Value.FLASH_INACTIVE_SLOT else Const.Value.FLASH_MAGISK
|
||||
|
||||
/* Flashing is understood as installing / flashing magisk itself */
|
||||
|
||||
fun flashIntent(context: Context, file: File, isSecondSlot: Boolean, id: Int = -1) = args(
|
||||
installer = file.toUri(),
|
||||
action = flashType(isSecondSlot),
|
||||
dismissId = id
|
||||
).let { createIntent(context, it) }
|
||||
|
||||
fun flash(file: File, isSecondSlot: Boolean, id: Int) = toFlash(
|
||||
installer = file.toUri(),
|
||||
action = flashType(isSecondSlot),
|
||||
dismissId = id
|
||||
).let { BaseUIActivity.postDirections(it) }
|
||||
|
||||
/* Patching is understood as injecting img files with magisk */
|
||||
|
||||
fun patchIntent(context: Context, file: File, uri: Uri, id: Int = -1) = args(
|
||||
installer = file.toUri(),
|
||||
action = Const.Value.PATCH_FILE,
|
||||
additionalData = uri,
|
||||
dismissId = id
|
||||
).let { createIntent(context, it) }
|
||||
|
||||
fun patch(file: File, uri: Uri, id: Int) = toFlash(
|
||||
installer = file.toUri(),
|
||||
action = Const.Value.PATCH_FILE,
|
||||
additionalData = uri,
|
||||
dismissId = id
|
||||
).let { BaseUIActivity.postDirections(it) }
|
||||
|
||||
/* Uninstalling is understood as removing magisk entirely */
|
||||
|
||||
fun uninstallIntent(context: Context, file: File, id: Int = -1) = args(
|
||||
installer = file.toUri(),
|
||||
action = Const.Value.UNINSTALL,
|
||||
dismissId = id
|
||||
).let { createIntent(context, it) }
|
||||
|
||||
fun uninstall(file: File, id: Int) = toFlash(
|
||||
installer = file.toUri(),
|
||||
action = Const.Value.UNINSTALL,
|
||||
dismissId = id
|
||||
).let { BaseUIActivity.postDirections(it) }
|
||||
|
||||
/* Installing is understood as flashing modules / zips */
|
||||
|
||||
fun installIntent(context: Context, file: File, id: Int = -1) = args(
|
||||
installer = file.toUri(),
|
||||
action = Const.Value.FLASH_ZIP,
|
||||
dismissId = id
|
||||
).let { createIntent(context, it) }
|
||||
|
||||
fun install(file: File, id: Int) = toFlash(
|
||||
installer = file.toUri(),
|
||||
action = Const.Value.FLASH_ZIP,
|
||||
dismissId = id
|
||||
).let { BaseUIActivity.postDirections(it) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,141 @@
|
||||
package com.topjohnwu.magisk.ui.flash
|
||||
|
||||
import android.Manifest
|
||||
import android.content.res.Resources
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.view.MenuItem
|
||||
import androidx.core.os.postDelayed
|
||||
import androidx.databinding.ObservableArrayList
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.tasks.FlashResultListener
|
||||
import com.topjohnwu.magisk.core.tasks.Flashing
|
||||
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||
import com.topjohnwu.magisk.core.view.Notifications
|
||||
import com.topjohnwu.magisk.extensions.*
|
||||
import com.topjohnwu.magisk.model.binding.BindingAdapter
|
||||
import com.topjohnwu.magisk.model.entity.recycler.ConsoleItem
|
||||
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||
import com.topjohnwu.magisk.ui.base.BaseViewModel
|
||||
import com.topjohnwu.magisk.ui.base.diffListOf
|
||||
import com.topjohnwu.magisk.ui.base.itemBindingOf
|
||||
import com.topjohnwu.magisk.utils.KObservableField
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class FlashViewModel : BaseViewModel()
|
||||
class FlashViewModel(
|
||||
private val args: FlashFragmentArgs,
|
||||
private val resources: Resources
|
||||
) : BaseViewModel(),
|
||||
FlashResultListener {
|
||||
|
||||
val canShowReboot = Shell.rootAccess()
|
||||
val showRestartTitle = KObservableField(false)
|
||||
|
||||
val behaviorText = KObservableField(resources.getString(R.string.flashing))
|
||||
|
||||
val adapter = BindingAdapter<ConsoleItem>()
|
||||
val items = diffListOf<ConsoleItem>()
|
||||
val itemBinding = itemBindingOf<ConsoleItem>()
|
||||
|
||||
private val outItems = ObservableArrayList<String>()
|
||||
private val logItems =
|
||||
Collections.synchronizedList(mutableListOf<String>())
|
||||
|
||||
init {
|
||||
outItems.sendUpdatesTo(items) { it.map { ConsoleItem(it) } }
|
||||
outItems.copyNewInputInto(logItems)
|
||||
|
||||
args.dismissId.takeIf { it != -1 }?.also {
|
||||
Notifications.mgr.cancel(it)
|
||||
}
|
||||
val (installer, action, uri) = args
|
||||
startFlashing(installer, uri, action)
|
||||
}
|
||||
|
||||
private fun startFlashing(installer: Uri, uri: Uri?, action: String) {
|
||||
when (action) {
|
||||
Const.Value.FLASH_ZIP -> Flashing.Install(
|
||||
installer,
|
||||
outItems,
|
||||
logItems,
|
||||
this
|
||||
).exec()
|
||||
Const.Value.UNINSTALL -> Flashing.Uninstall(
|
||||
installer,
|
||||
outItems,
|
||||
logItems,
|
||||
this
|
||||
).exec()
|
||||
Const.Value.FLASH_MAGISK -> MagiskInstaller.Direct(
|
||||
installer,
|
||||
outItems,
|
||||
logItems,
|
||||
this
|
||||
).exec()
|
||||
Const.Value.FLASH_INACTIVE_SLOT -> MagiskInstaller.SecondSlot(
|
||||
installer,
|
||||
outItems,
|
||||
logItems,
|
||||
this
|
||||
).exec()
|
||||
Const.Value.PATCH_FILE -> MagiskInstaller.Patch(
|
||||
installer,
|
||||
uri ?: return,
|
||||
outItems,
|
||||
logItems,
|
||||
this
|
||||
).exec()
|
||||
else -> backPressed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResult(success: Boolean) {
|
||||
state = if (success) State.LOADED else State.LOADING_FAILED
|
||||
behaviorText.value = when {
|
||||
success -> resources.getString(R.string.done)
|
||||
else -> resources.getString(R.string.failure)
|
||||
}
|
||||
|
||||
if (success) {
|
||||
Handler().postDelayed(500) {
|
||||
showRestartTitle.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onMenuItemClicked(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_save -> savePressed()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun savePressed() = withPermissions(
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
)
|
||||
.map { now }
|
||||
.map { it.toTime(timeFormatStandard) }
|
||||
.map { Const.MAGISK_INSTALL_LOG_FILENAME.format(it) }
|
||||
.map { File(Config.downloadDirectory, it) }
|
||||
.map { file ->
|
||||
file.bufferedWriter().use { writer ->
|
||||
logItems.forEach {
|
||||
writer.write(it)
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
file.path
|
||||
}
|
||||
.subscribeK { SnackbarEvent(it).publish() }
|
||||
.add()
|
||||
|
||||
fun restartPressed() = reboot()
|
||||
|
||||
fun backPressed() = back()
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user