mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 16:07:39 +00:00
Move SplashActivity logic into core module
This commit is contained in:
parent
fcb7ebb090
commit
ddae568741
@ -1,6 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.ui
|
package com.topjohnwu.magisk.ui
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
@ -8,35 +9,45 @@ import android.os.Bundle
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.NavDirections
|
import androidx.navigation.NavDirections
|
||||||
import com.topjohnwu.magisk.MainDirections
|
import com.topjohnwu.magisk.MainDirections
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
|
import com.topjohnwu.magisk.arch.NavigationActivity
|
||||||
import com.topjohnwu.magisk.arch.startAnimations
|
import com.topjohnwu.magisk.arch.startAnimations
|
||||||
import com.topjohnwu.magisk.arch.viewModel
|
import com.topjohnwu.magisk.arch.viewModel
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.base.SplashController
|
||||||
|
import com.topjohnwu.magisk.core.base.SplashScreenHost
|
||||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||||
|
import com.topjohnwu.magisk.core.ktx.toast
|
||||||
import com.topjohnwu.magisk.core.model.module.LocalModule
|
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||||
|
import com.topjohnwu.magisk.core.tasks.AppMigration
|
||||||
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
|
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
|
||||||
import com.topjohnwu.magisk.ui.home.HomeFragmentDirections
|
import com.topjohnwu.magisk.ui.home.HomeFragmentDirections
|
||||||
|
import com.topjohnwu.magisk.ui.theme.Theme
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
import com.topjohnwu.magisk.view.Shortcuts
|
import com.topjohnwu.magisk.view.Shortcuts
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import com.topjohnwu.magisk.core.R as CoreR
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class MainViewModel : BaseViewModel()
|
class MainViewModel : BaseViewModel()
|
||||||
|
|
||||||
class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
class MainActivity : NavigationActivity<ActivityMainMd2Binding>(), SplashScreenHost {
|
||||||
|
|
||||||
override val layoutRes = R.layout.activity_main_md2
|
override val layoutRes = R.layout.activity_main_md2
|
||||||
override val viewModel by viewModel<MainViewModel>()
|
override val viewModel by viewModel<MainViewModel>()
|
||||||
override val navHostId: Int = R.id.main_nav_host
|
override val navHostId: Int = R.id.main_nav_host
|
||||||
|
override val splashController = SplashController(this)
|
||||||
override val snackbarView: View
|
override val snackbarView: View
|
||||||
get() {
|
get() {
|
||||||
val fragmentOverride = currentFragment?.snackbarView
|
val fragmentOverride = currentFragment?.snackbarView
|
||||||
@ -54,8 +65,20 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
|||||||
|
|
||||||
private var isRootFragment = true
|
private var isRootFragment = true
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
setTheme(Theme.selected.themeRes)
|
||||||
|
splashController.preOnCreate()
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
splashController.onCreate(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
splashController.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
override fun showMainUI(savedInstanceState: Bundle?) {
|
override fun onCreateUi(savedInstanceState: Bundle?) {
|
||||||
setContentView()
|
setContentView()
|
||||||
showUnsupportedMessage()
|
showUnsupportedMessage()
|
||||||
askForHomeShortcut()
|
askForHomeShortcut()
|
||||||
@ -165,6 +188,31 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("InlinedApi")
|
||||||
|
override fun showInvalidStateMessage(): Unit = runOnUiThread {
|
||||||
|
MagiskDialog(this).apply {
|
||||||
|
setTitle(CoreR.string.unsupport_nonroot_stub_title)
|
||||||
|
setMessage(CoreR.string.unsupport_nonroot_stub_msg)
|
||||||
|
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||||
|
text = CoreR.string.install
|
||||||
|
onClick {
|
||||||
|
withPermission(REQUEST_INSTALL_PACKAGES) {
|
||||||
|
if (!it) {
|
||||||
|
toast(CoreR.string.install_unknown_denied, Toast.LENGTH_SHORT)
|
||||||
|
showInvalidStateMessage()
|
||||||
|
} else {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
AppMigration.restore(this@MainActivity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCancelable(false)
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun showUnsupportedMessage() {
|
private fun showUnsupportedMessage() {
|
||||||
if (Info.env.isUnsupported) {
|
if (Info.env.isUnsupported) {
|
||||||
MagiskDialog(this).apply {
|
MagiskDialog(this).apply {
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.ui
|
|
||||||
|
|
||||||
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
|
||||||
import androidx.databinding.ViewDataBinding
|
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.topjohnwu.magisk.arch.NavigationActivity
|
|
||||||
import com.topjohnwu.magisk.core.R
|
|
||||||
import com.topjohnwu.magisk.core.base.relaunch
|
|
||||||
import com.topjohnwu.magisk.core.initializeOnSplashScreen
|
|
||||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
|
||||||
import com.topjohnwu.magisk.core.ktx.toast
|
|
||||||
import com.topjohnwu.magisk.core.tasks.AppMigration
|
|
||||||
import com.topjohnwu.magisk.ui.theme.Theme
|
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
|
||||||
import com.topjohnwu.superuser.Shell
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@SuppressLint("CustomSplashScreen")
|
|
||||||
abstract class SplashActivity<Binding : ViewDataBinding> : NavigationActivity<Binding>() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private var splashShown = false
|
|
||||||
}
|
|
||||||
|
|
||||||
private var needShowMainUI = false
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
setTheme(Theme.selected.themeRes)
|
|
||||||
|
|
||||||
if (isRunningAsStub && !splashShown) {
|
|
||||||
// Manually apply splash theme for stub
|
|
||||||
theme.applyStyle(R.style.StubSplashTheme, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
if (!isRunningAsStub) {
|
|
||||||
val splashScreen = installSplashScreen()
|
|
||||||
splashScreen.setKeepOnScreenCondition { !splashShown }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splashShown) {
|
|
||||||
doShowMainUI(savedInstanceState)
|
|
||||||
} else {
|
|
||||||
Shell.getShell(Shell.EXECUTOR) {
|
|
||||||
if (isRunningAsStub && !it.isRoot) {
|
|
||||||
showInvalidStateMessage()
|
|
||||||
return@getShell
|
|
||||||
}
|
|
||||||
initializeOnSplashScreen {
|
|
||||||
splashShown = true
|
|
||||||
if (isRunningAsStub) {
|
|
||||||
// Re-launch main activity without splash theme
|
|
||||||
relaunch()
|
|
||||||
} else {
|
|
||||||
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
|
|
||||||
doShowMainUI(savedInstanceState)
|
|
||||||
} else {
|
|
||||||
needShowMainUI = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doShowMainUI(savedInstanceState: Bundle?) {
|
|
||||||
needShowMainUI = false
|
|
||||||
showMainUI(savedInstanceState)
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun showMainUI(savedInstanceState: Bundle?)
|
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
|
||||||
private fun showInvalidStateMessage(): Unit = runOnUiThread {
|
|
||||||
MagiskDialog(this).apply {
|
|
||||||
setTitle(R.string.unsupport_nonroot_stub_title)
|
|
||||||
setMessage(R.string.unsupport_nonroot_stub_msg)
|
|
||||||
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
|
||||||
text = R.string.install
|
|
||||||
onClick {
|
|
||||||
withPermission(REQUEST_INSTALL_PACKAGES) {
|
|
||||||
if (!it) {
|
|
||||||
toast(R.string.install_unknown_denied, Toast.LENGTH_SHORT)
|
|
||||||
showInvalidStateMessage()
|
|
||||||
} else {
|
|
||||||
lifecycleScope.launch {
|
|
||||||
AppMigration.restore(this@SplashActivity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCancelable(false)
|
|
||||||
show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
if (needShowMainUI) {
|
|
||||||
doShowMainUI(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -63,7 +63,7 @@ dependencies {
|
|||||||
implementation("androidx.room:room-ktx:${vRoom}")
|
implementation("androidx.room:room-ktx:${vRoom}")
|
||||||
ksp("androidx.room:room-compiler:${vRoom}")
|
ksp("androidx.room:room-compiler:${vRoom}")
|
||||||
|
|
||||||
api("androidx.core:core-splashscreen:1.0.1")
|
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||||
implementation("androidx.core:core-ktx:1.13.1")
|
implementation("androidx.core:core-ktx:1.13.1")
|
||||||
implementation("androidx.activity:activity:1.9.0")
|
implementation("androidx.activity:activity:1.9.0")
|
||||||
implementation("androidx.collection:collection-ktx:1.4.1")
|
implementation("androidx.collection:collection-ktx:1.4.1")
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.topjohnwu.magisk.core
|
package com.topjohnwu.magisk.core
|
||||||
|
|
||||||
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.app.LocaleManager
|
import android.app.LocaleManager
|
||||||
@ -12,24 +11,15 @@ import android.os.Build
|
|||||||
import android.os.Build.VERSION.SDK_INT
|
import android.os.Build.VERSION.SDK_INT
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.system.Os
|
import android.system.Os
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.profileinstaller.ProfileInstaller
|
import androidx.profileinstaller.ProfileInstaller
|
||||||
import com.topjohnwu.magisk.StubApk
|
import com.topjohnwu.magisk.StubApk
|
||||||
import com.topjohnwu.magisk.core.BuildConfig.APP_PACKAGE_NAME
|
|
||||||
import com.topjohnwu.magisk.core.base.IActivityExtension
|
|
||||||
import com.topjohnwu.magisk.core.base.UntrackedActivity
|
import com.topjohnwu.magisk.core.base.UntrackedActivity
|
||||||
import com.topjohnwu.magisk.core.base.launchPackage
|
|
||||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
|
||||||
import com.topjohnwu.magisk.core.ktx.writeTo
|
|
||||||
import com.topjohnwu.magisk.core.tasks.AppMigration
|
|
||||||
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
||||||
import com.topjohnwu.magisk.core.utils.NetworkObserver
|
import com.topjohnwu.magisk.core.utils.NetworkObserver
|
||||||
import com.topjohnwu.magisk.core.utils.ProcessLifecycle
|
import com.topjohnwu.magisk.core.utils.ProcessLifecycle
|
||||||
import com.topjohnwu.magisk.core.utils.RootUtils
|
import com.topjohnwu.magisk.core.utils.RootUtils
|
||||||
import com.topjohnwu.magisk.core.utils.ShellInit
|
import com.topjohnwu.magisk.core.utils.ShellInit
|
||||||
import com.topjohnwu.magisk.view.Notifications
|
import com.topjohnwu.magisk.view.Notifications
|
||||||
import com.topjohnwu.magisk.view.Shortcuts
|
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
import com.topjohnwu.superuser.ipc.RootService
|
import com.topjohnwu.superuser.ipc.RootService
|
||||||
@ -38,8 +28,6 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import kotlinx.coroutines.asExecutor
|
import kotlinx.coroutines.asExecutor
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
|
||||||
import java.io.IOException
|
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
@ -141,71 +129,3 @@ object AppContext : ContextWrapper(null),
|
|||||||
override fun onLowMemory() {}
|
override fun onLowMemory() {}
|
||||||
override fun onTrimMemory(level: Int) {}
|
override fun onTrimMemory(level: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> T.initializeOnSplashScreen(launchUi: Runnable)
|
|
||||||
where T : ComponentActivity, T : IActivityExtension {
|
|
||||||
val prevPkg = launchPackage
|
|
||||||
val prevConfig = intent.getBundleExtra(Const.Key.PREV_CONFIG)
|
|
||||||
val isPackageMigration = prevPkg != null && prevConfig != null
|
|
||||||
|
|
||||||
Config.init(prevConfig)
|
|
||||||
|
|
||||||
if (packageName != APP_PACKAGE_NAME) {
|
|
||||||
runCatching {
|
|
||||||
// Hidden, remove com.topjohnwu.magisk if exist as it could be malware
|
|
||||||
packageManager.getApplicationInfo(APP_PACKAGE_NAME, 0)
|
|
||||||
Shell.cmd("(pm uninstall $APP_PACKAGE_NAME)& >/dev/null 2>&1").exec()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (Config.suManager.isNotEmpty()) {
|
|
||||||
Config.suManager = ""
|
|
||||||
}
|
|
||||||
if (isPackageMigration) {
|
|
||||||
Shell.cmd("(pm uninstall $prevPkg)& >/dev/null 2>&1").exec()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPackageMigration) {
|
|
||||||
runOnUiThread {
|
|
||||||
// Relaunch the process after package migration
|
|
||||||
StubApk.restartProcess(this)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate stub APK
|
|
||||||
if (isRunningAsStub && (
|
|
||||||
// Version mismatch
|
|
||||||
Info.stub!!.version != BuildConfig.STUB_VERSION ||
|
|
||||||
// Not properly patched
|
|
||||||
intent.component!!.className.contains(AppMigration.PLACEHOLDER))
|
|
||||||
) {
|
|
||||||
withPermission(REQUEST_INSTALL_PACKAGES) { granted ->
|
|
||||||
if (granted) {
|
|
||||||
lifecycleScope.launch {
|
|
||||||
val apk = File(cacheDir, "stub.apk")
|
|
||||||
try {
|
|
||||||
assets.open("stub.apk").writeTo(apk)
|
|
||||||
AppMigration.upgradeStub(this@initializeOnSplashScreen, apk)?.let {
|
|
||||||
startActivity(it)
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
|
||||||
Timber.e(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
JobService.schedule(this)
|
|
||||||
Shortcuts.setupDynamic(this)
|
|
||||||
|
|
||||||
// Pre-fetch network services
|
|
||||||
ServiceLocator.networkService
|
|
||||||
|
|
||||||
// Wait for root service
|
|
||||||
RootUtils.Connection.await()
|
|
||||||
|
|
||||||
runOnUiThread(launchUi)
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,159 @@
|
|||||||
|
package com.topjohnwu.magisk.core.base
|
||||||
|
|
||||||
|
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.topjohnwu.magisk.StubApk
|
||||||
|
import com.topjohnwu.magisk.core.BuildConfig
|
||||||
|
import com.topjohnwu.magisk.core.BuildConfig.APP_PACKAGE_NAME
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.JobService
|
||||||
|
import com.topjohnwu.magisk.core.R
|
||||||
|
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||||
|
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||||
|
import com.topjohnwu.magisk.core.ktx.writeTo
|
||||||
|
import com.topjohnwu.magisk.core.tasks.AppMigration
|
||||||
|
import com.topjohnwu.magisk.core.utils.RootUtils
|
||||||
|
import com.topjohnwu.magisk.view.Shortcuts
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
interface SplashScreenHost : IActivityExtension {
|
||||||
|
val splashController: SplashController<*>
|
||||||
|
|
||||||
|
fun onCreateUi(savedInstanceState: Bundle?)
|
||||||
|
fun showInvalidStateMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
class SplashController<T>(private val activity: T)
|
||||||
|
where T : ComponentActivity, T: SplashScreenHost {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private var splashShown = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private var shouldCreateUiOnResume = false
|
||||||
|
|
||||||
|
fun preOnCreate() {
|
||||||
|
if (isRunningAsStub && !splashShown) {
|
||||||
|
// Manually apply splash theme for stub
|
||||||
|
activity.theme.applyStyle(R.style.StubSplashTheme, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
if (!isRunningAsStub) {
|
||||||
|
val splashScreen = activity.installSplashScreen()
|
||||||
|
splashScreen.setKeepOnScreenCondition { !splashShown }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splashShown) {
|
||||||
|
doCreateUi(savedInstanceState)
|
||||||
|
} else {
|
||||||
|
Shell.getShell(Shell.EXECUTOR) {
|
||||||
|
if (isRunningAsStub && !it.isRoot) {
|
||||||
|
activity.showInvalidStateMessage()
|
||||||
|
return@getShell
|
||||||
|
}
|
||||||
|
activity.initializeApp()
|
||||||
|
activity.runOnUiThread {
|
||||||
|
splashShown = true
|
||||||
|
if (isRunningAsStub) {
|
||||||
|
// Re-launch main activity without splash theme
|
||||||
|
activity.relaunch()
|
||||||
|
} else {
|
||||||
|
if (activity.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
|
||||||
|
doCreateUi(savedInstanceState)
|
||||||
|
} else {
|
||||||
|
shouldCreateUiOnResume = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onResume() {
|
||||||
|
if (shouldCreateUiOnResume) {
|
||||||
|
doCreateUi(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doCreateUi(savedInstanceState: Bundle?) {
|
||||||
|
shouldCreateUiOnResume = false
|
||||||
|
activity.onCreateUi(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun T.initializeApp() {
|
||||||
|
val prevPkg = launchPackage
|
||||||
|
val prevConfig = intent.getBundleExtra(Const.Key.PREV_CONFIG)
|
||||||
|
val isPackageMigration = prevPkg != null && prevConfig != null
|
||||||
|
|
||||||
|
Config.init(prevConfig)
|
||||||
|
|
||||||
|
if (packageName != APP_PACKAGE_NAME) {
|
||||||
|
runCatching {
|
||||||
|
// Hidden, remove com.topjohnwu.magisk if exist as it could be malware
|
||||||
|
packageManager.getApplicationInfo(APP_PACKAGE_NAME, 0)
|
||||||
|
Shell.cmd("(pm uninstall $APP_PACKAGE_NAME)& >/dev/null 2>&1").exec()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Config.suManager.isNotEmpty()) {
|
||||||
|
Config.suManager = ""
|
||||||
|
}
|
||||||
|
if (isPackageMigration) {
|
||||||
|
Shell.cmd("(pm uninstall $prevPkg)& >/dev/null 2>&1").exec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPackageMigration) {
|
||||||
|
runOnUiThread {
|
||||||
|
// Relaunch the process after package migration
|
||||||
|
StubApk.restartProcess(this)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate stub APK
|
||||||
|
if (isRunningAsStub && (
|
||||||
|
// Version mismatch
|
||||||
|
Info.stub!!.version != BuildConfig.STUB_VERSION ||
|
||||||
|
// Not properly patched
|
||||||
|
intent.component!!.className.contains(AppMigration.PLACEHOLDER))
|
||||||
|
) {
|
||||||
|
withPermission(REQUEST_INSTALL_PACKAGES) { granted ->
|
||||||
|
if (granted) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val apk = File(cacheDir, "stub.apk")
|
||||||
|
try {
|
||||||
|
assets.open("stub.apk").writeTo(apk)
|
||||||
|
AppMigration.upgradeStub(activity, apk)?.let {
|
||||||
|
startActivity(it)
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Timber.e(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
JobService.schedule(this)
|
||||||
|
Shortcuts.setupDynamic(this)
|
||||||
|
|
||||||
|
// Pre-fetch network services
|
||||||
|
ServiceLocator.networkService
|
||||||
|
|
||||||
|
// Wait for root service
|
||||||
|
RootUtils.Connection.await()
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user