Fix installing extensions on MIUI (#8916)
* Fix installing extensions on MIUI * isShizukuReady -> isShizukuInstalled
This commit is contained in:
parent
c637172ee0
commit
293b967858
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
@ -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",
|
||||||
|
@ -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
|
||||||
|
@ -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>()
|
||||||
|
@ -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) {
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user