Fix installing extensions on MIUI (#8916)

* Fix installing extensions on MIUI

* isShizukuReady -> isShizukuInstalled
This commit is contained in:
stevenyomi 2023-01-15 23:32:27 +08:00 committed by GitHub
parent c637172ee0
commit 293b967858
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 105 additions and 45 deletions

View File

@ -2,9 +2,6 @@ package eu.kanade.domain.base
import android.content.Context import android.content.Context
import eu.kanade.tachiyomi.core.preference.PreferenceStore 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.isPreviewBuildType
import eu.kanade.tachiyomi.util.system.isReleaseBuildType import eu.kanade.tachiyomi.util.system.isReleaseBuildType
@ -21,10 +18,7 @@ class BasePreferences(
fun automaticExtUpdates() = preferenceStore.getBoolean("automatic_ext_updates", true) fun automaticExtUpdates() = preferenceStore.getBoolean("automatic_ext_updates", true)
fun extensionInstaller() = preferenceStore.getEnum( fun extensionInstaller() = ExtensionInstallerPreference(context, preferenceStore)
"extension_installer",
if (DeviceUtil.isMiui) PreferenceValues.ExtensionInstaller.LEGACY else PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER,
)
fun acraEnabled() = preferenceStore.getBoolean("acra.enable", isPreviewBuildType || isReleaseBuildType) fun acraEnabled() = preferenceStore.getBoolean("acra.enable", isPreviewBuildType || isReleaseBuildType)
} }

View File

@ -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<ExtensionInstaller> {
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)
}

View File

@ -2,7 +2,6 @@ package eu.kanade.presentation.browse
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -32,7 +31,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp 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.FastScrollLazyColumn
import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.LoadingScreen
import eu.kanade.presentation.components.PullRefresh import eu.kanade.presentation.components.PullRefresh
import eu.kanade.presentation.components.WarningBanner
import eu.kanade.presentation.manga.components.DotSeparatorNoSpaceText import eu.kanade.presentation.manga.components.DotSeparatorNoSpaceText
import eu.kanade.presentation.theme.header import eu.kanade.presentation.theme.header
import eu.kanade.presentation.util.padding 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.extension.model.InstallStep
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionUiModel import eu.kanade.tachiyomi.ui.browse.extension.ExtensionUiModel
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsState import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsState
import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
@Composable @Composable
@ -123,29 +119,10 @@ private fun ExtensionContent(
onClickUpdateAll: () -> Unit, onClickUpdateAll: () -> Unit,
) { ) {
var trustState by remember { mutableStateOf<Extension.Untrusted?>(null) } var trustState by remember { mutableStateOf<Extension.Untrusted?>(null) }
val showMiuiWarning = DeviceUtil.isMiui && DeviceUtil.miuiMajorVersion >= 13 && !DeviceUtil.isMiuiOptimizationDisabled()
val uriHandler = LocalUriHandler.current
FastScrollLazyColumn( FastScrollLazyColumn(
contentPadding = if (showMiuiWarning) { contentPadding = contentPadding + topSmallPaddingValues,
contentPadding
} else {
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) -> state.items.forEach { (header, items) ->
item( item(
contentType = "header", contentType = "header",

View File

@ -52,10 +52,9 @@ import eu.kanade.tachiyomi.network.PREF_DOH_SHECAN
import eu.kanade.tachiyomi.util.CrashLogUtil import eu.kanade.tachiyomi.util.CrashLogUtil
import eu.kanade.tachiyomi.util.lang.launchNonCancellable import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.lang.withUIContext 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.isPreviewBuildType
import eu.kanade.tachiyomi.util.system.isReleaseBuildType 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.logcat
import eu.kanade.tachiyomi.util.system.powerManager import eu.kanade.tachiyomi.util.system.powerManager
import eu.kanade.tachiyomi.util.system.setDefaultSettings import eu.kanade.tachiyomi.util.system.setDefaultSettings
@ -63,7 +62,6 @@ import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.LogPriority import logcat.LogPriority
import okhttp3.Headers import okhttp3.Headers
import rikka.sui.Sui
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import java.io.File
@ -344,6 +342,7 @@ object SettingsAdvancedScreen : SearchableSettings {
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
val context = LocalContext.current val context = LocalContext.current
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
val extensionInstallerPref = basePreferences.extensionInstaller()
var shizukuMissing by rememberSaveable { mutableStateOf(false) } var shizukuMissing by rememberSaveable { mutableStateOf(false) }
if (shizukuMissing) { if (shizukuMissing) {
@ -373,19 +372,13 @@ object SettingsAdvancedScreen : SearchableSettings {
title = stringResource(R.string.label_extensions), title = stringResource(R.string.label_extensions),
preferenceItems = listOf( preferenceItems = listOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = basePreferences.extensionInstaller(), pref = extensionInstallerPref,
title = stringResource(R.string.ext_installer_pref), title = stringResource(R.string.ext_installer_pref),
entries = PreferenceValues.ExtensionInstaller.values() entries = extensionInstallerPref.entries
.run { .associateWith { stringResource(it.titleResId) },
if (DeviceUtil.isMiui) {
filter { it != PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER }
} else {
toList()
}
}.associateWith { stringResource(it.titleResId) },
onValueChanged = { onValueChanged = {
if (it == PreferenceValues.ExtensionInstaller.SHIZUKU && if (it == PreferenceValues.ExtensionInstaller.SHIZUKU &&
!(context.isPackageInstalled("moe.shizuku.privileged.api") || Sui.isSui()) !context.isShizukuInstalled
) { ) {
shizukuMissing = true shizukuMissing = true
false false

View File

@ -5,9 +5,11 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.util.system.hasMiuiPackageInstaller
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get 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 * 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() { 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?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -23,6 +30,11 @@ class ExtensionInstallActivity : Activity() {
.putExtra(Intent.EXTRA_RETURN_RESULT, true) .putExtra(Intent.EXTRA_RETURN_RESULT, true)
.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
if (hasMiuiPackageInstaller) {
ignoreResult = true
ignoreUntil = System.nanoTime() + 1.seconds.inWholeNanoseconds
}
try { try {
startActivityForResult(installIntent, INSTALL_REQUEST_CODE) startActivityForResult(installIntent, INSTALL_REQUEST_CODE)
} catch (error: Exception) { } catch (error: Exception) {
@ -33,12 +45,24 @@ class ExtensionInstallActivity : Activity() {
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (ignoreResult && System.nanoTime() < ignoreUntil) {
hasIgnoredResult = true
return
}
if (requestCode == INSTALL_REQUEST_CODE) { if (requestCode == INSTALL_REQUEST_CODE) {
checkInstallationResult(resultCode) checkInstallationResult(resultCode)
} }
finish() finish()
} }
override fun onStart() {
super.onStart()
if (hasIgnoredResult) {
checkInstallationResult(RESULT_CANCELED)
finish()
}
}
private fun checkInstallationResult(resultCode: Int) { private fun checkInstallationResult(resultCode: Int) {
val downloadId = intent.extras!!.getLong(ExtensionInstaller.EXTRA_DOWNLOAD_ID) val downloadId = intent.extras!!.getLong(ExtensionInstaller.EXTRA_DOWNLOAD_ID)
val extensionManager = Injekt.get<ExtensionManager>() val extensionManager = Injekt.get<ExtensionManager>()

View File

@ -41,6 +41,7 @@ import eu.kanade.tachiyomi.ui.base.delegate.ThemingDelegate
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.util.lang.truncateCenter import eu.kanade.tachiyomi.util.lang.truncateCenter
import logcat.LogPriority import logcat.LogPriority
import rikka.sui.Sui
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File 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 { fun Context.isInstalledFromFDroid(): Boolean {
val installerPackageName = try { val installerPackageName = try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {

View File

@ -305,7 +305,6 @@
<string name="ext_installer_shizuku" translatable="false">Shizuku</string> <string name="ext_installer_shizuku" translatable="false">Shizuku</string>
<string name="ext_installer_shizuku_stopped">Shizuku is not running</string> <string name="ext_installer_shizuku_stopped">Shizuku is not running</string>
<string name="ext_installer_shizuku_unavailable_dialog">Install and start Shizuku to use Shizuku as extension installer.</string> <string name="ext_installer_shizuku_unavailable_dialog">Install and start Shizuku to use Shizuku as extension installer.</string>
<string name="ext_miui_warning">If installing extensions isn\'t working, try disabling MIUI Optimization or tap here to download from the website instead.</string>
<!-- Reader section --> <!-- Reader section -->
<string name="pref_fullscreen">Fullscreen</string> <string name="pref_fullscreen">Fullscreen</string>