Commit 022c217c authored by topjohnwu's avatar topjohnwu

Migrate to SplashScreen API

parent 81f57949
......@@ -129,5 +129,6 @@ dependencies {
implementation("androidx.fragment:fragment-ktx:1.3.6")
implementation("androidx.transition:transition:1.4.1")
implementation("androidx.core:core-ktx:1.7.0")
implementation("androidx.core:core-splashscreen:1.0.0-alpha02")
implementation("com.google.android.material:material:1.4.0")
}
......@@ -13,7 +13,7 @@
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning">
<activity
android:name=".core.SplashActivity"
android:name=".ui.MainActivity"
android:exported="true"
android:theme="@style/SplashTheme">
<intent-filter>
......@@ -26,10 +26,6 @@
</intent-filter>
</activity>
<activity
android:name=".ui.MainActivity"
android:exported="false" />
<activity
android:name=".ui.surequest.SuRequestActivity"
android:directBootAware="true"
......
package com.topjohnwu.magisk.core
package com.topjohnwu.magisk.arch
import android.content.Intent
import android.net.Uri
import android.os.Build.VERSION.SDK_INT
import android.os.Bundle
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.databinding.ViewDataBinding
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.JobService
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.di.ServiceLocator
import com.topjohnwu.magisk.ui.MainActivity
import com.topjohnwu.magisk.ui.theme.Theme
import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.magisk.view.Notifications
import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell
import java.util.concurrent.CountDownLatch
class SplashActivity : BaseActivity() {
abstract class BaseMainActivity<VM : BaseViewModel, Binding : ViewDataBinding>
: BaseUIActivity<VM, Binding>() {
private val latch = CountDownLatch(1)
companion object {
private var doPreload = true
}
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.SplashTheme)
setTheme(Theme.selected.themeRes)
if (isRunningAsStub && doPreload) {
// Manually apply splash theme for stub
if (SDK_INT >= 31) {
theme.applyStyle(R.style.StubSplashTheme, true)
} else {
theme.applyStyle(R.style.SplashTheme, true)
}
}
super.onCreate(savedInstanceState)
// Pre-initialize root shell
Shell.getShell(null) { initAndStart() }
if (!isRunningAsStub) {
val splashScreen = installSplashScreen()
splashScreen.setKeepVisibleCondition { doPreload }
}
private fun handleRepackage(pkg: String?) {
if (packageName != APPLICATION_ID) {
runCatching {
// Hidden, remove com.topjohnwu.magisk if exist as it could be malware
packageManager.getApplicationInfo(APPLICATION_ID, 0)
Shell.su("(pm uninstall $APPLICATION_ID)& >/dev/null 2>&1").exec()
if (doPreload) {
// Pre-initialize root shell
Shell.getShell(null) {
if (isRunningAsStub && !Shell.rootAccess()) {
showInvalidStateMessage()
return@getShell
}
preLoad()
runOnUiThread {
doPreload = false
if (isRunningAsStub) {
// Re-launch main activity without splash theme
recreate()
} else {
if (Config.suManager.isNotEmpty())
Config.suManager = ""
pkg ?: return
if (!Shell.su("(pm uninstall $pkg)& >/dev/null 2>&1").exec().isSuccess)
uninstallApp(pkg)
showMainUI(savedInstanceState)
}
}
}
} else {
showMainUI(savedInstanceState)
}
}
private fun initAndStart() {
if (isRunningAsStub && !Shell.rootAccess()) {
abstract fun showMainUI(savedInstanceState: Bundle?)
private fun showInvalidStateMessage() {
runOnUiThread {
MagiskDialog(this)
.applyTitle(R.string.unsupport_nonroot_stub_title)
.applyMessage(R.string.unsupport_nonroot_stub_msg)
.applyButton(MagiskDialog.ButtonType.POSITIVE) {
titleRes = R.string.install
onClick { HideAPK.restore(this@SplashActivity) }
onClick { HideAPK.restore(this@BaseMainActivity) }
}
.cancellable(false)
.reveal()
}
return
}
private fun preLoad() {
val prevPkg = intent.getStringExtra(Const.Key.PREV_PKG)
Config.load(prevPkg)
......@@ -68,10 +99,22 @@ class SplashActivity : BaseActivity() {
// Pre-fetch network services
ServiceLocator.networkService
}
DONE = true
startActivity(redirect<MainActivity>())
finish()
private fun handleRepackage(pkg: String?) {
if (packageName != APPLICATION_ID) {
runCatching {
// Hidden, remove com.topjohnwu.magisk if exist as it could be malware
packageManager.getApplicationInfo(APPLICATION_ID, 0)
Shell.su("(pm uninstall $APPLICATION_ID)& >/dev/null 2>&1").exec()
}
} else {
if (Config.suManager.isNotEmpty())
Config.suManager = ""
pkg ?: return
if (!Shell.su("(pm uninstall $pkg)& >/dev/null 2>&1").exec().isSuccess)
uninstallApp(pkg)
}
}
@Suppress("DEPRECATION")
......@@ -84,8 +127,4 @@ class SplashActivity : BaseActivity() {
}
latch.await()
}
companion object {
var DONE = false
}
}
......@@ -17,14 +17,12 @@ import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.arch.inflater.LayoutInflaterFactory
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.ui.theme.Theme
abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
BaseActivity(), BaseUIComponent<VM> {
protected lateinit var binding: Binding
protected abstract val layoutRes: Int
protected open val themeRes: Int = Theme.selected.themeRes
private val navHostFragment by lazy {
supportFragmentManager.findFragmentById(navHostId) as? NavHostFragment
......@@ -46,7 +44,6 @@ abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
override fun onCreate(savedInstanceState: Bundle?) {
layoutInflater.factory2 = LayoutInflaterFactory(delegate)
setTheme(themeRes)
super.onCreate(savedInstanceState)
startObserveEvents()
......
......@@ -16,7 +16,7 @@ import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
import androidx.navigation.NavDirections
import com.topjohnwu.magisk.MainDirections
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIActivity
import com.topjohnwu.magisk.arch.BaseMainActivity
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.arch.ReselectionTarget
import com.topjohnwu.magisk.core.*
......@@ -31,7 +31,7 @@ import java.io.File
class MainViewModel : BaseViewModel()
open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>() {
class MainActivity : BaseMainActivity<MainViewModel, ActivityMainMd2Binding>() {
override val layoutRes = R.layout.activity_main_md2
override val viewModel by viewModel<MainViewModel>()
......@@ -39,16 +39,7 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
private var isRootFragment = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Make sure Splash is always ran before us
if (!SplashActivity.DONE) {
redirect<SplashActivity>().also { startActivity(it) }
finish()
return
}
override fun showMainUI(savedInstanceState: Bundle?) {
setContentView()
showUnsupportedMessage()
askForHomeShortcut()
......@@ -83,9 +74,16 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
binding.mainNavigation.setOnItemReselectedListener {
(currentFragment as? ReselectionTarget)?.onReselected()
}
binding.mainNavigation.menu.apply {
findItem(R.id.superuserFragment)?.isEnabled = Utils.showSuperUser()
}
val section =
if (intent.action == Intent.ACTION_APPLICATION_PREFERENCES)
Const.Nav.SETTINGS
else
intent.getStringExtra(Const.Key.OPEN_SECTION)
val section = if (intent.action == Intent.ACTION_APPLICATION_PREFERENCES) Const.Nav.SETTINGS
else intent.getStringExtra(Const.Key.OPEN_SECTION)
getScreen(section)?.navigate()
if (savedInstanceState != null) {
......@@ -95,13 +93,6 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
}
}
override fun onResume() {
super.onResume()
binding.mainNavigation.menu.apply {
findItem(R.id.superuserFragment)?.isEnabled = Utils.showSuperUser()
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> onBackPressed()
......
......@@ -14,6 +14,7 @@ import com.topjohnwu.magisk.core.su.SuCallbackHandler
import com.topjohnwu.magisk.core.su.SuCallbackHandler.REQUEST
import com.topjohnwu.magisk.databinding.ActivityRequestBinding
import com.topjohnwu.magisk.di.viewModel
import com.topjohnwu.magisk.ui.theme.Theme
open class SuRequestActivity : BaseUIActivity<SuRequestViewModel, ActivityRequestBinding>() {
......@@ -33,6 +34,7 @@ open class SuRequestActivity : BaseUIActivity<SuRequestViewModel, ActivityReques
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
window.setHideOverlayWindows(true)
}
setTheme(Theme.selected.themeRes)
super.onCreate(savedInstanceState)
fun showRequest() {
......
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="SplashTheme" parent="Theme.Splash" />
<style name="Foundation" parent="Theme.Foundation" />
</resources>
......@@ -8,10 +8,9 @@
<style name="Theme.Foundation.Light" parent="Base.V23.Theme.Foundation.Light" />
<style name="Base.V23.Theme.Splash.Light" parent="Base.V21.Theme.Splash.Light">
<item name="android:windowLightStatusBar">false</item>
<style name="Theme.Splash" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/splash_background</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_magisk_padded</item>
</style>
<style name="Theme.Splash.Light" parent="Base.V23.Theme.Splash.Light" />
</resources>
......@@ -15,10 +15,4 @@
<style name="Theme.Foundation" parent="Base.V27.Theme.Foundation" />
<style name="Base.V27.Theme.Splash.Light" parent="Base.V23.Theme.Splash.Light">
<item name="android:windowLightNavigationBar">false</item>
</style>
<style name="Theme.Splash.Light" parent="Base.V27.Theme.Splash.Light" />
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- For stub APK, we need to manually handle the SplashScreen -->
<style name="StubSplashTheme" parent="Theme.SplashScreenBase">
<item name="android:enforceStatusBarContrast">false</item>
<item name="android:enforceNavigationBarContrast">false</item>
<item name="windowSplashScreenBackground">@color/splash_background</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_magisk_padded</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="SplashTheme" parent="Theme.Splash.Light" />
<style name="SplashTheme" parent="Theme.Splash" />
<style name="Foundation" parent="Theme.Foundation.Light" />
......
......@@ -21,30 +21,10 @@
<style name="Theme.Foundation" parent="Base.V21.Theme.Foundation" />
<style name="Base.V21.Theme.Splash.Light" parent="Theme.MaterialComponents.Light.NoActionBar">
<style name="Theme.Splash" parent="Theme.SplashScreen">
<item name="android:windowBackground">@drawable/ic_splash_activity</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
<style name="Base.V21.Theme.Splash" parent="Theme.MaterialComponents.NoActionBar">
<item name="android:windowBackground">@drawable/ic_splash_activity</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
<style name="Theme.Splash.Light" parent="Base.V21.Theme.Splash.Light" />
<style name="Theme.Splash" parent="Base.V21.Theme.Splash" />
<style name="Base.V21.ThemeOverlay.Foundation.Dialog" parent="ThemeOverlay.MaterialComponents.Dialog">
<item name="android:windowMinWidthMajor">@dimen/abc_dialog_min_width_major</item>
<item name="android:windowMinWidthMinor">@dimen/abc_dialog_min_width_minor</item>
......
......@@ -137,7 +137,7 @@ fun genStubManifest(srcDir: File, outDir: File): String {
))
cmpList.add(Component(
"com.topjohnwu.magisk.core.SplashActivity",
"com.topjohnwu.magisk.ui.MainActivity",
"DownloadActivity",
"""
|<activity
......@@ -150,15 +150,6 @@ fun genStubManifest(srcDir: File, outDir: File): String {
|</activity>""".ind(2)
))
cmpList.add(Component(
"com.topjohnwu.magisk.ui.MainActivity",
"",
"""
|<activity
| android:name="%s"
| android:exported="false" />""".ind(2)
))
cmpList.add(Component(
"com.topjohnwu.magisk.ui.surequest.SuRequestActivity",
"",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment