diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b84152fa8..bd2209947 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
(Protected)
val xml = File(
"${context.filesDir.parent}/shared_prefs",
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt
index ea5df7f6c..d867738b3 100644
--- a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt
@@ -83,6 +83,7 @@ object Const {
}
object Nav {
+ const val HOME = "home"
const val SETTINGS = "settings"
const val HIDE = "hide"
const val MODULES = "modules"
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/GeneralReceiver.kt b/app/src/main/java/com/topjohnwu/magisk/core/GeneralReceiver.kt
index dd81b365c..1d370b8cd 100644
--- a/app/src/main/java/com/topjohnwu/magisk/core/GeneralReceiver.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/core/GeneralReceiver.kt
@@ -45,7 +45,7 @@ open class GeneralReceiver : BaseReceiver() {
rmPolicy(pkg)
Shell.su("magiskhide --rm $pkg").submit()
}
- Intent.ACTION_LOCALE_CHANGED -> Shortcuts.setup(context)
+ Intent.ACTION_LOCALE_CHANGED -> Shortcuts.setupDynamic(context)
Const.Key.BROADCAST_MANAGER_UPDATE -> {
intent.getParcelableExtra(Const.Key.INTENT_SET_APP)?.let {
Info.remote = Info.remote.copy(app = it)
diff --git a/app/src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt b/app/src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt
index 606533c7c..bb48ddc85 100644
--- a/app/src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/core/SplashActivity.kt
@@ -52,7 +52,7 @@ open class SplashActivity : Activity() {
handleRepackage()
Notifications.setup(this)
UpdateCheckService.schedule(this)
- Shortcuts.setup(this)
+ Shortcuts.setupDynamic(this)
// Pre-fetch network stuffs
get()
diff --git a/app/src/main/java/com/topjohnwu/magisk/events/ViewEvents.kt b/app/src/main/java/com/topjohnwu/magisk/events/ViewEvents.kt
index 0751e1de4..69fbad00b 100644
--- a/app/src/main/java/com/topjohnwu/magisk/events/ViewEvents.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/events/ViewEvents.kt
@@ -8,6 +8,7 @@ import com.topjohnwu.magisk.arch.*
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.core.model.module.Repo
import com.topjohnwu.magisk.view.MarkDownWindow
+import com.topjohnwu.magisk.view.Shortcuts
import kotlinx.coroutines.launch
class ViewActionEvent(val action: BaseActivity.() -> Unit) : ViewEvent(), ActivityExecutor {
@@ -82,3 +83,9 @@ class NavigationEvent(
}
}
}
+
+class AddHomeIconEvent : ViewEvent(), ContextExecutor {
+ override fun invoke(context: Context) {
+ Shortcuts.addHomeIcon(context)
+ }
+}
diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt
index e77464c4f..2f0de7b5d 100644
--- a/app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt
@@ -8,20 +8,19 @@ import android.view.View
import android.view.ViewTreeObserver
import android.view.WindowManager
import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.view.forEach
import androidx.core.view.setPadding
import androidx.core.view.updateLayoutParams
import androidx.navigation.NavDirections
import com.google.android.material.card.MaterialCardView
+import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.MainDirections
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIActivity
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.arch.ReselectionTarget
-import com.topjohnwu.magisk.core.Const
-import com.topjohnwu.magisk.core.Info
-import com.topjohnwu.magisk.core.SplashActivity
-import com.topjohnwu.magisk.core.redirect
+import com.topjohnwu.magisk.core.*
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
import com.topjohnwu.magisk.ktx.startAnimations
import com.topjohnwu.magisk.ui.home.HomeFragmentDirections
@@ -29,6 +28,7 @@ import com.topjohnwu.magisk.utils.HideBottomViewOnScrollBehavior
import com.topjohnwu.magisk.utils.HideTopViewOnScrollBehavior
import com.topjohnwu.magisk.utils.HideableBehavior
import com.topjohnwu.magisk.view.MagiskDialog
+import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -60,14 +60,8 @@ open class MainActivity : BaseUIActivity(
return
}
- if (Info.env.isUnsupported) {
- MagiskDialog(this)
- .applyTitle(R.string.unsupport_magisk_title)
- .applyMessage(R.string.unsupport_magisk_msg, Const.Version.MIN_VERSION)
- .applyButton(MagiskDialog.ButtonType.POSITIVE) { titleRes = android.R.string.ok }
- .cancellable(true)
- .reveal()
- }
+ showUnsupportedMessage()
+ askForHomeShortcut()
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
@@ -189,6 +183,40 @@ open class MainActivity : BaseUIActivity(
}
}
+ private fun showUnsupportedMessage() {
+ if (Info.env.isUnsupported) {
+ MagiskDialog(this)
+ .applyTitle(R.string.unsupport_magisk_title)
+ .applyMessage(R.string.unsupport_magisk_msg, Const.Version.MIN_VERSION)
+ .applyButton(MagiskDialog.ButtonType.POSITIVE) { titleRes = android.R.string.ok }
+ .cancellable(true)
+ .reveal()
+ }
+ }
+
+ private fun askForHomeShortcut() {
+ // Don't bother if we are not hidden
+ if (packageName == BuildConfig.APPLICATION_ID)
+ return
+
+ if (!Config.askedHome && ShortcutManagerCompat.isRequestPinShortcutSupported(this)) {
+ // Ask and show dialog
+ Config.askedHome = true
+ MagiskDialog(this)
+ .applyTitle(R.string.add_shortcut_title)
+ .applyMessage(R.string.add_shortcut_msg)
+ .applyButton(MagiskDialog.ButtonType.NEGATIVE) {
+ titleRes = R.string.no
+ }.applyButton(MagiskDialog.ButtonType.POSITIVE) {
+ titleRes = R.string.yes
+ onClick {
+ Shortcuts.addHomeIcon(this@MainActivity)
+ }
+ }.cancellable(true)
+ .reveal()
+ }
+ }
+
companion object {
private val ACTION_APPLICATION_PREFERENCES get() =
if (Build.VERSION.SDK_INT >= 24) Intent.ACTION_APPLICATION_PREFERENCES
diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt
index f90be7083..70722047d 100644
--- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsItems.kt
@@ -103,9 +103,10 @@ object Restore : BaseSettingsItem.Blank() {
override val description = R.string.settings_restore_manager_summary.asTransitive()
}
-@Suppress("FunctionName")
-fun HideOrRestore() =
- if (get().packageName == BuildConfig.APPLICATION_ID) Hide else Restore
+object AddShortcut : BaseSettingsItem.Blank() {
+ override val title = R.string.add_shortcut_title.asTransitive()
+ override val description = R.string.setting_add_shortcut_summary.asTransitive()
+}
object DownloadPath : BaseSettingsItem.Input() {
override var value = Config.downloadPath
diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt
index 9d148ee10..d758ec764 100644
--- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt
@@ -1,10 +1,13 @@
package com.topjohnwu.magisk.ui.settings
+import android.content.Context
import android.os.Build
import android.view.View
import android.widget.Toast
+import androidx.core.content.pm.ShortcutManagerCompat
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
+import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.arch.adapterOf
@@ -17,6 +20,7 @@ import com.topjohnwu.magisk.core.download.DownloadService
import com.topjohnwu.magisk.core.download.DownloadSubject
import com.topjohnwu.magisk.core.utils.PatchAPK
import com.topjohnwu.magisk.data.database.RepoDao
+import com.topjohnwu.magisk.events.AddHomeIconEvent
import com.topjohnwu.magisk.events.RecreateEvent
import com.topjohnwu.magisk.events.dialog.BiometricDialog
import com.topjohnwu.magisk.utils.Utils
@@ -39,6 +43,9 @@ class SettingsViewModel(
}
private fun createItems(): List {
+ val context = get()
+ val hidden = context.packageName != BuildConfig.APPLICATION_ID
+
// Customization
val list = mutableListOf(
Customization,
@@ -49,6 +56,8 @@ class SettingsViewModel(
// making theming a pain in the ass. Just forget about it
list.remove(Theme)
}
+ if (hidden && ShortcutManagerCompat.isRequestPinShortcutSupported(context))
+ list.add(AddShortcut)
// Manager
list.addAll(listOf(
@@ -58,7 +67,7 @@ class SettingsViewModel(
if (Info.env.isActive) {
list.add(ClearRepoCache)
if (Const.USER_ID == 0 && Info.isConnected.get())
- list.add(HideOrRestore())
+ list.add(if (hidden) Restore else Hide)
}
// Magisk
@@ -96,6 +105,7 @@ class SettingsViewModel(
is ClearRepoCache -> clearRepoCache()
is SystemlessHosts -> createHosts()
is Restore -> restoreManager()
+ is AddShortcut -> AddHomeIconEvent().publish()
else -> callback()
}
diff --git a/app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.kt b/app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.kt
index 3d058907f..36aa2892b 100644
--- a/app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.kt
@@ -4,53 +4,62 @@ import android.content.Context
import android.content.Intent
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
-import android.graphics.drawable.Icon
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService
-import androidx.core.graphics.drawable.toAdaptiveIcon
-import androidx.core.graphics.drawable.toIcon
+import androidx.core.content.pm.ShortcutInfoCompat
+import androidx.core.content.pm.ShortcutManagerCompat
+import androidx.core.graphics.drawable.IconCompat
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
-import com.topjohnwu.magisk.core.SplashActivity
-import com.topjohnwu.magisk.core.intent
import com.topjohnwu.magisk.ktx.getBitmap
import com.topjohnwu.magisk.utils.Utils
object Shortcuts {
- fun setup(context: Context) {
+ fun setupDynamic(context: Context) {
if (Build.VERSION.SDK_INT >= 25) {
- val manager = context.getSystemService()
- manager?.dynamicShortcuts =
- getShortCuts(context)
+ val manager = context.getSystemService() ?: return
+ manager.dynamicShortcuts = getShortCuts(context)
}
}
+ fun addHomeIcon(context: Context) {
+ val intent = context.packageManager.getLaunchIntentForPackage(context.packageName) ?: return
+ val info = ShortcutInfoCompat.Builder(context, Const.Nav.HOME)
+ .setShortLabel(context.getString(R.string.app_name))
+ .setIntent(intent)
+ .setIcon(context.getIconCompat(R.drawable.ic_launcher))
+ .build()
+ ShortcutManagerCompat.requestPinShortcut(context, info, null)
+ }
+
+ private fun Context.getIconCompat(id: Int): IconCompat {
+ return if (Build.VERSION.SDK_INT >= 26)
+ IconCompat.createWithAdaptiveBitmap(getBitmap(id))
+ else
+ IconCompat.createWithBitmap(getBitmap(id))
+ }
+
+ @RequiresApi(api = 23)
+ private fun Context.getIcon(id: Int) = getIconCompat(id).toIcon(this)
+
@RequiresApi(api = 25)
private fun getShortCuts(context: Context): List {
- val shortCuts = mutableListOf()
- val intent = context.intent()
+ val intent = context.packageManager.getLaunchIntentForPackage(context.packageName)
+ ?: return emptyList()
- fun getIcon(id: Int): Icon {
- return if (Build.VERSION.SDK_INT >= 26)
- context.getBitmap(id).toAdaptiveIcon()
- else
- context.getBitmap(id).toIcon()
- }
+ val shortCuts = mutableListOf()
if (Utils.showSuperUser()) {
shortCuts.add(
ShortcutInfo.Builder(context, Const.Nav.SUPERUSER)
.setShortLabel(context.getString(R.string.superuser))
.setIntent(
- Intent(intent)
- .putExtra(Const.Key.OPEN_SECTION, Const.Nav.SUPERUSER)
- .setAction(Intent.ACTION_VIEW)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ Intent(intent).putExtra(Const.Key.OPEN_SECTION, Const.Nav.SUPERUSER)
)
- .setIcon(getIcon(R.drawable.sc_superuser))
+ .setIcon(context.getIcon(R.drawable.sc_superuser))
.setRank(0)
.build()
)
@@ -60,12 +69,9 @@ object Shortcuts {
ShortcutInfo.Builder(context, Const.Nav.HIDE)
.setShortLabel(context.getString(R.string.magiskhide))
.setIntent(
- Intent(intent)
- .putExtra(Const.Key.OPEN_SECTION, Const.Nav.HIDE)
- .setAction(Intent.ACTION_VIEW)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ Intent(intent).putExtra(Const.Key.OPEN_SECTION, Const.Nav.HIDE)
)
- .setIcon(getIcon(R.drawable.sc_magiskhide))
+ .setIcon(context.getIcon(R.drawable.sc_magiskhide))
.setRank(1)
.build()
)
@@ -75,12 +81,9 @@ object Shortcuts {
ShortcutInfo.Builder(context, Const.Nav.MODULES)
.setShortLabel(context.getString(R.string.modules))
.setIntent(
- Intent(intent)
- .putExtra(Const.Key.OPEN_SECTION, Const.Nav.MODULES)
- .setAction(Intent.ACTION_VIEW)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ Intent(intent).putExtra(Const.Key.OPEN_SECTION, Const.Nav.MODULES)
)
- .setIcon(getIcon(R.drawable.sc_extension))
+ .setIcon(context.getIcon(R.drawable.sc_extension))
.setRank(2)
.build()
)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 449e5f309..66deedde5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -174,6 +174,7 @@
Use biometric authentication to allow superuser requests
Unsupported device or no biometric settings are enabled
Customization
+ Add a pretty shortcut in the home screen in case the name and icon are difficult to recognize after hiding the app
Multiuser Mode
Device Owner Only
@@ -231,5 +232,7 @@
Unsupported Magisk Version
This version of Magisk Manager does not support Magisk version lower than %1$s.\n\nThe app will behave as if no Magisk is installed, please upgrade Magisk as soon as possible.
Grant storage permission to enable this functionality
+ Add shortcut to home screen
+ After hiding Magisk Manager, its name and icon might become difficult to recognize. Do you want to add a pretty shortcut to the home screen?