mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-01-11 23:23:37 +00:00
Better stub launch flow
This commit is contained in:
parent
fa60daf9b5
commit
317153c53a
@ -27,8 +27,7 @@ abstract class UIActivity<Binding : ViewDataBinding> : BaseActivity(), ViewModel
|
|||||||
open val snackbarAnchorView: View? get() = null
|
open val snackbarAnchorView: View? get() = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val theme = Config.darkTheme
|
AppCompatDelegate.setDefaultNightMode(Config.darkTheme)
|
||||||
AppCompatDelegate.setDefaultNightMode(theme)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -2,6 +2,7 @@ package com.topjohnwu.magisk.core.base
|
|||||||
|
|
||||||
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||||
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
import android.app.Activity
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -54,6 +55,18 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||||||
uninstallLatch.countDown()
|
uninstallLatch.countDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val mReferrerField by lazy(LazyThreadSafetyMode.NONE) {
|
||||||
|
Activity::class.java.reflectField("mReferrer")
|
||||||
|
}
|
||||||
|
|
||||||
|
val realCallingPackage: String? get() {
|
||||||
|
callingPackage?.let { return it }
|
||||||
|
if (Build.VERSION.SDK_INT >= 22) {
|
||||||
|
mReferrerField.get(this)?.let { return it as String }
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
super.attachBaseContext(base.wrap())
|
super.attachBaseContext(base.wrap())
|
||||||
}
|
}
|
||||||
|
@ -99,8 +99,7 @@ object HideAPK {
|
|||||||
val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
activity.grantUriPermission(pkg, Provider.preferencesUri(self), flag)
|
activity.grantUriPermission(pkg, Provider.preferencesUri(self), flag)
|
||||||
intent.putExtra(Const.Key.PREV_PKG, self)
|
intent.putExtra(Const.Key.PREV_PKG, self)
|
||||||
intent.flags = 0
|
activity.startActivity(intent)
|
||||||
activity.startActivityForResult(intent, Int.MAX_VALUE)
|
|
||||||
activity.finish()
|
activity.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package com.topjohnwu.magisk.events.dialog
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.arch.UIActivity
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
|
|
||||||
@ -33,6 +34,6 @@ class DarkThemeDialog : DialogEvent() {
|
|||||||
|
|
||||||
private fun selectTheme(mode: Int, activity: Activity) {
|
private fun selectTheme(mode: Int, activity: Activity) {
|
||||||
Config.darkTheme = mode
|
Config.darkTheme = mode
|
||||||
activity.recreate()
|
(activity as UIActivity<*>).delegate.localNightMode = mode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import androidx.core.view.isVisible
|
|||||||
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.BaseMainActivity
|
|
||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
import com.topjohnwu.magisk.arch.viewModel
|
import com.topjohnwu.magisk.arch.viewModel
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
@ -31,7 +30,7 @@ import java.io.File
|
|||||||
|
|
||||||
class MainViewModel : BaseViewModel()
|
class MainViewModel : BaseViewModel()
|
||||||
|
|
||||||
class MainActivity : BaseMainActivity<ActivityMainMd2Binding>() {
|
class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
||||||
|
|
||||||
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>()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.arch
|
package com.topjohnwu.magisk.ui
|
||||||
|
|
||||||
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
@ -9,7 +9,7 @@ import androidx.databinding.ViewDataBinding
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
|
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.StubApk
|
import com.topjohnwu.magisk.arch.NavigationActivity
|
||||||
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.JobService
|
import com.topjohnwu.magisk.core.JobService
|
||||||
@ -25,16 +25,17 @@ import com.topjohnwu.magisk.view.Shortcuts
|
|||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<Binding>() {
|
@SuppressLint("CustomSplashScreen")
|
||||||
|
abstract class SplashActivity<Binding : ViewDataBinding> : NavigationActivity<Binding>() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private var doPreload = true
|
private var skipSplash = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
setTheme(Theme.selected.themeRes)
|
setTheme(Theme.selected.themeRes)
|
||||||
|
|
||||||
if (isRunningAsStub && doPreload) {
|
if (isRunningAsStub && !skipSplash) {
|
||||||
// Manually apply splash theme for stub
|
// Manually apply splash theme for stub
|
||||||
theme.applyStyle(R.style.StubSplashTheme, true)
|
theme.applyStyle(R.style.StubSplashTheme, true)
|
||||||
}
|
}
|
||||||
@ -43,28 +44,19 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
|
|||||||
|
|
||||||
if (!isRunningAsStub) {
|
if (!isRunningAsStub) {
|
||||||
val splashScreen = installSplashScreen()
|
val splashScreen = installSplashScreen()
|
||||||
splashScreen.setKeepOnScreenCondition { doPreload }
|
splashScreen.setKeepOnScreenCondition { !skipSplash }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doPreload) {
|
if (skipSplash) {
|
||||||
|
showMainUI(savedInstanceState)
|
||||||
|
} else {
|
||||||
Shell.getShell(Shell.EXECUTOR) {
|
Shell.getShell(Shell.EXECUTOR) {
|
||||||
if (isRunningAsStub && !it.isRoot) {
|
if (isRunningAsStub && !it.isRoot) {
|
||||||
showInvalidStateMessage()
|
showInvalidStateMessage()
|
||||||
return@getShell
|
return@getShell
|
||||||
}
|
}
|
||||||
preLoad()
|
preLoad(savedInstanceState)
|
||||||
runOnUiThread {
|
|
||||||
doPreload = false
|
|
||||||
if (isRunningAsStub) {
|
|
||||||
// Re-launch main activity without splash theme
|
|
||||||
relaunch()
|
|
||||||
} else {
|
|
||||||
showMainUI(savedInstanceState)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
showMainUI(savedInstanceState)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +76,7 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
|
|||||||
showInvalidStateMessage()
|
showInvalidStateMessage()
|
||||||
} else {
|
} else {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
HideAPK.restore(this@BaseMainActivity)
|
HideAPK.restore(this@SplashActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,10 +87,10 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun preLoad() {
|
private fun preLoad(savedState: Bundle?) {
|
||||||
val prevPkg = intent.getStringExtra(Const.Key.PREV_PKG)?.let {
|
val prevPkg = intent.getStringExtra(Const.Key.PREV_PKG)?.let {
|
||||||
// Make sure the calling package matches (prevent DoS)
|
// Make sure the calling package matches (prevent DoS)
|
||||||
if (it == callingPackage)
|
if (it == realCallingPackage)
|
||||||
it
|
it
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
@ -106,9 +98,14 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
|
|||||||
|
|
||||||
Config.load(prevPkg)
|
Config.load(prevPkg)
|
||||||
handleRepackage(prevPkg)
|
handleRepackage(prevPkg)
|
||||||
if (prevPkg != null) {
|
if (prevPkg != null && !isRunningAsStub) {
|
||||||
StubApk.restartProcess(this)
|
runOnUiThread {
|
||||||
|
// Might have new configuration loaded, relaunch the activity
|
||||||
|
relaunch()
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Notifications.setup(this)
|
Notifications.setup(this)
|
||||||
JobService.schedule(this)
|
JobService.schedule(this)
|
||||||
Shortcuts.setupDynamic(this)
|
Shortcuts.setupDynamic(this)
|
||||||
@ -118,6 +115,16 @@ abstract class BaseMainActivity<Binding : ViewDataBinding> : NavigationActivity<
|
|||||||
|
|
||||||
// Wait for root service
|
// Wait for root service
|
||||||
RootUtils.Connection.await()
|
RootUtils.Connection.await()
|
||||||
|
|
||||||
|
runOnUiThread {
|
||||||
|
skipSplash = true
|
||||||
|
if (isRunningAsStub) {
|
||||||
|
// Re-launch main activity without splash theme
|
||||||
|
relaunch()
|
||||||
|
} else {
|
||||||
|
showMainUI(savedState)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRepackage(pkg: String?) {
|
private fun handleRepackage(pkg: String?) {
|
@ -1,6 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.ui.theme
|
package com.topjohnwu.magisk.ui.theme
|
||||||
|
|
||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.events.RecreateEvent
|
import com.topjohnwu.magisk.events.RecreateEvent
|
||||||
import com.topjohnwu.magisk.events.dialog.DarkThemeDialog
|
import com.topjohnwu.magisk.events.dialog.DarkThemeDialog
|
||||||
import com.topjohnwu.magisk.view.TappableHeadlineItem
|
import com.topjohnwu.magisk.view.TappableHeadlineItem
|
||||||
@ -10,15 +11,13 @@ class ThemeViewModel : BaseViewModel(), TappableHeadlineItem.Listener {
|
|||||||
val themeHeadline = TappableHeadlineItem.ThemeMode
|
val themeHeadline = TappableHeadlineItem.ThemeMode
|
||||||
|
|
||||||
override fun onItemPressed(item: TappableHeadlineItem) = when (item) {
|
override fun onItemPressed(item: TappableHeadlineItem) = when (item) {
|
||||||
is TappableHeadlineItem.ThemeMode -> darkModePressed()
|
is TappableHeadlineItem.ThemeMode -> DarkThemeDialog().publish()
|
||||||
else -> Unit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveTheme(theme: Theme) {
|
fun saveTheme(theme: Theme) {
|
||||||
theme.select()
|
if (!theme.isSelected) {
|
||||||
RecreateEvent().publish()
|
Config.themeOrdinal = theme.ordinal
|
||||||
|
RecreateEvent().publish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun darkModePressed() = DarkThemeDialog().publish()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user