From 293b96785865d9cf8c62b3e12046347b32be9d4d Mon Sep 17 00:00:00 2001 From: stevenyomi <95685115+stevenyomi@users.noreply.github.com> Date: Sun, 15 Jan 2023 23:32:27 +0800 Subject: [PATCH] Fix installing extensions on MIUI (#8916) * Fix installing extensions on MIUI * isShizukuReady -> isShizukuInstalled --- .../eu/kanade/domain/base/BasePreferences.kt | 8 +-- .../base/ExtensionInstallerPreference.kt | 68 +++++++++++++++++++ .../presentation/browse/ExtensionsScreen.kt | 25 +------ .../settings/screen/SettingsAdvancedScreen.kt | 19 ++---- .../util/ExtensionInstallActivity.kt | 24 +++++++ .../util/system/ContextExtensions.kt | 5 ++ i18n/src/main/res/values/strings.xml | 1 - 7 files changed, 105 insertions(+), 45 deletions(-) create mode 100644 app/src/main/java/eu/kanade/domain/base/ExtensionInstallerPreference.kt diff --git a/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt b/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt index 892bb24b3b..986856c0c6 100644 --- a/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt +++ b/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt @@ -2,9 +2,6 @@ package eu.kanade.domain.base import android.content.Context import eu.kanade.tachiyomi.core.preference.PreferenceStore -import eu.kanade.tachiyomi.core.preference.getEnum -import eu.kanade.tachiyomi.data.preference.PreferenceValues -import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.isPreviewBuildType import eu.kanade.tachiyomi.util.system.isReleaseBuildType @@ -21,10 +18,7 @@ class BasePreferences( fun automaticExtUpdates() = preferenceStore.getBoolean("automatic_ext_updates", true) - fun extensionInstaller() = preferenceStore.getEnum( - "extension_installer", - if (DeviceUtil.isMiui) PreferenceValues.ExtensionInstaller.LEGACY else PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER, - ) + fun extensionInstaller() = ExtensionInstallerPreference(context, preferenceStore) fun acraEnabled() = preferenceStore.getBoolean("acra.enable", isPreviewBuildType || isReleaseBuildType) } diff --git a/app/src/main/java/eu/kanade/domain/base/ExtensionInstallerPreference.kt b/app/src/main/java/eu/kanade/domain/base/ExtensionInstallerPreference.kt new file mode 100644 index 0000000000..89fc27b7fd --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/base/ExtensionInstallerPreference.kt @@ -0,0 +1,68 @@ +package eu.kanade.domain.base + +import android.content.Context +import eu.kanade.tachiyomi.core.preference.Preference +import eu.kanade.tachiyomi.core.preference.PreferenceStore +import eu.kanade.tachiyomi.core.preference.getEnum +import eu.kanade.tachiyomi.data.preference.PreferenceValues.ExtensionInstaller +import eu.kanade.tachiyomi.util.system.hasMiuiPackageInstaller +import eu.kanade.tachiyomi.util.system.isShizukuInstalled +import kotlinx.coroutines.CoroutineScope + +class ExtensionInstallerPreference( + private val context: Context, + preferenceStore: PreferenceStore, +) : Preference { + + private val basePref = preferenceStore.getEnum(key(), defaultValue()) + + override fun key() = "extension_installer" + + val entries get() = ExtensionInstaller.values().run { + if (context.hasMiuiPackageInstaller) { + filter { it != ExtensionInstaller.PACKAGEINSTALLER } + } else { + toList() + } + } + + override fun defaultValue() = if (context.hasMiuiPackageInstaller) { + ExtensionInstaller.LEGACY + } else { + ExtensionInstaller.PACKAGEINSTALLER + } + + private fun check(value: ExtensionInstaller): ExtensionInstaller { + when (value) { + ExtensionInstaller.PACKAGEINSTALLER -> { + if (context.hasMiuiPackageInstaller) return ExtensionInstaller.LEGACY + } + ExtensionInstaller.SHIZUKU -> { + if (!context.isShizukuInstalled) return defaultValue() + } + else -> {} + } + return value + } + + override fun get(): ExtensionInstaller { + val value = basePref.get() + val checkedValue = check(value) + if (value != checkedValue) { + basePref.set(checkedValue) + } + return checkedValue + } + + override fun set(value: ExtensionInstaller) { + basePref.set(check(value)) + } + + override fun isSet() = basePref.isSet() + + override fun delete() = basePref.delete() + + override fun changes() = basePref.changes() + + override fun stateIn(scope: CoroutineScope) = basePref.stateIn(scope) +} diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt index c711eaed65..452784e61e 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt @@ -2,7 +2,6 @@ package eu.kanade.presentation.browse import androidx.annotation.StringRes import androidx.compose.animation.core.animateDpAsState -import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -32,7 +31,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -43,7 +41,6 @@ import eu.kanade.presentation.components.EmptyScreen import eu.kanade.presentation.components.FastScrollLazyColumn import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.PullRefresh -import eu.kanade.presentation.components.WarningBanner import eu.kanade.presentation.manga.components.DotSeparatorNoSpaceText import eu.kanade.presentation.theme.header import eu.kanade.presentation.util.padding @@ -55,7 +52,6 @@ import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.ui.browse.extension.ExtensionUiModel import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsState -import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.LocaleHelper @Composable @@ -123,29 +119,10 @@ private fun ExtensionContent( onClickUpdateAll: () -> Unit, ) { var trustState by remember { mutableStateOf(null) } - val showMiuiWarning = DeviceUtil.isMiui && DeviceUtil.miuiMajorVersion >= 13 && !DeviceUtil.isMiuiOptimizationDisabled() - val uriHandler = LocalUriHandler.current FastScrollLazyColumn( - contentPadding = if (showMiuiWarning) { - contentPadding - } else { - contentPadding + topSmallPaddingValues - }, + contentPadding = contentPadding + topSmallPaddingValues, ) { - if (showMiuiWarning) { - item { - WarningBanner( - textRes = R.string.ext_miui_warning, - modifier = Modifier - .padding(bottom = MaterialTheme.padding.small) - .clickable { - uriHandler.openUri("https://tachiyomi.org/extensions") - }, - ) - } - } - state.items.forEach { (header, items) -> item( contentType = "header", diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt index 37a2fc56cf..1f0a13d6db 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt @@ -52,10 +52,9 @@ import eu.kanade.tachiyomi.network.PREF_DOH_SHECAN import eu.kanade.tachiyomi.util.CrashLogUtil import eu.kanade.tachiyomi.util.lang.launchNonCancellable import eu.kanade.tachiyomi.util.lang.withUIContext -import eu.kanade.tachiyomi.util.system.DeviceUtil -import eu.kanade.tachiyomi.util.system.isPackageInstalled import eu.kanade.tachiyomi.util.system.isPreviewBuildType import eu.kanade.tachiyomi.util.system.isReleaseBuildType +import eu.kanade.tachiyomi.util.system.isShizukuInstalled import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.powerManager import eu.kanade.tachiyomi.util.system.setDefaultSettings @@ -63,7 +62,6 @@ import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.launch import logcat.LogPriority import okhttp3.Headers -import rikka.sui.Sui import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File @@ -344,6 +342,7 @@ object SettingsAdvancedScreen : SearchableSettings { ): Preference.PreferenceGroup { val context = LocalContext.current val uriHandler = LocalUriHandler.current + val extensionInstallerPref = basePreferences.extensionInstaller() var shizukuMissing by rememberSaveable { mutableStateOf(false) } if (shizukuMissing) { @@ -373,19 +372,13 @@ object SettingsAdvancedScreen : SearchableSettings { title = stringResource(R.string.label_extensions), preferenceItems = listOf( Preference.PreferenceItem.ListPreference( - pref = basePreferences.extensionInstaller(), + pref = extensionInstallerPref, title = stringResource(R.string.ext_installer_pref), - entries = PreferenceValues.ExtensionInstaller.values() - .run { - if (DeviceUtil.isMiui) { - filter { it != PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER } - } else { - toList() - } - }.associateWith { stringResource(it.titleResId) }, + entries = extensionInstallerPref.entries + .associateWith { stringResource(it.titleResId) }, onValueChanged = { if (it == PreferenceValues.ExtensionInstaller.SHIZUKU && - !(context.isPackageInstalled("moe.shizuku.privileged.api") || Sui.isSui()) + !context.isShizukuInstalled ) { shizukuMissing = true false diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstallActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstallActivity.kt index a1d01a02f2..37ac84e44c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstallActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstallActivity.kt @@ -5,9 +5,11 @@ import android.content.Intent import android.os.Bundle import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.model.InstallStep +import eu.kanade.tachiyomi.util.system.hasMiuiPackageInstaller import eu.kanade.tachiyomi.util.system.toast import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import kotlin.time.Duration.Companion.seconds /** * Activity used to install extensions, because we can only receive the result of the installation @@ -15,6 +17,11 @@ import uy.kohesive.injekt.api.get */ class ExtensionInstallActivity : Activity() { + // MIUI package installer bug workaround + private var ignoreUntil = 0L + private var ignoreResult = false + private var hasIgnoredResult = false + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -23,6 +30,11 @@ class ExtensionInstallActivity : Activity() { .putExtra(Intent.EXTRA_RETURN_RESULT, true) .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + if (hasMiuiPackageInstaller) { + ignoreResult = true + ignoreUntil = System.nanoTime() + 1.seconds.inWholeNanoseconds + } + try { startActivityForResult(installIntent, INSTALL_REQUEST_CODE) } catch (error: Exception) { @@ -33,12 +45,24 @@ class ExtensionInstallActivity : Activity() { } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (ignoreResult && System.nanoTime() < ignoreUntil) { + hasIgnoredResult = true + return + } if (requestCode == INSTALL_REQUEST_CODE) { checkInstallationResult(resultCode) } finish() } + override fun onStart() { + super.onStart() + if (hasIgnoredResult) { + checkInstallationResult(RESULT_CANCELED) + finish() + } + } + private fun checkInstallationResult(resultCode: Int) { val downloadId = intent.extras!!.getLong(ExtensionInstaller.EXTRA_DOWNLOAD_ID) val extensionManager = Injekt.get() diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt index 29cbc68b13..75f9c36b27 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt @@ -41,6 +41,7 @@ import eu.kanade.tachiyomi.ui.base.delegate.ThemingDelegate import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.util.lang.truncateCenter import logcat.LogPriority +import rikka.sui.Sui import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File @@ -350,6 +351,10 @@ fun Context.isPackageInstalled(packageName: String): Boolean { } } +val Context.hasMiuiPackageInstaller get() = isPackageInstalled("com.miui.packageinstaller") + +val Context.isShizukuInstalled get() = isPackageInstalled("moe.shizuku.privileged.api") || Sui.isSui() + fun Context.isInstalledFromFDroid(): Boolean { val installerPackageName = try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index e7afd2658b..4965f2c1ee 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -305,7 +305,6 @@ Shizuku Shizuku is not running Install and start Shizuku to use Shizuku as extension installer. - If installing extensions isn\'t working, try disabling MIUI Optimization or tap here to download from the website instead. Fullscreen