feat: allow specify custom installer for LegacyInstaller
Useful for customizing installation behavior.
This commit is contained in:
parent
2e5a61d136
commit
815aebe28c
@ -14,6 +14,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey
|
|||||||
import androidx.datastore.preferences.core.stringSetPreferencesKey
|
import androidx.datastore.preferences.core.stringSetPreferencesKey
|
||||||
import com.looker.droidify.datastore.model.AutoSync
|
import com.looker.droidify.datastore.model.AutoSync
|
||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyPreference
|
import com.looker.droidify.datastore.model.ProxyPreference
|
||||||
import com.looker.droidify.datastore.model.ProxyType
|
import com.looker.droidify.datastore.model.ProxyType
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
@ -85,6 +86,16 @@ class PreferenceSettingsRepository(
|
|||||||
override suspend fun setInstallerType(installerType: InstallerType) =
|
override suspend fun setInstallerType(installerType: InstallerType) =
|
||||||
INSTALLER_TYPE.update(installerType.name)
|
INSTALLER_TYPE.update(installerType.name)
|
||||||
|
|
||||||
|
override suspend fun setLegacyInstallerComponent(component: LegacyInstallerComponent?) {
|
||||||
|
if (component == null) {
|
||||||
|
LEGACY_INSTALLER_COMPONENT_CLASS.update("")
|
||||||
|
LEGACY_INSTALLER_COMPONENT_ACTIVITY.update("")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
LEGACY_INSTALLER_COMPONENT_CLASS.update(component.clazz)
|
||||||
|
LEGACY_INSTALLER_COMPONENT_ACTIVITY.update(component.activity)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun setAutoUpdate(allow: Boolean) =
|
override suspend fun setAutoUpdate(allow: Boolean) =
|
||||||
AUTO_UPDATE.update(allow)
|
AUTO_UPDATE.update(allow)
|
||||||
|
|
||||||
@ -125,6 +136,12 @@ class PreferenceSettingsRepository(
|
|||||||
private fun mapSettings(preferences: Preferences): Settings {
|
private fun mapSettings(preferences: Preferences): Settings {
|
||||||
val installerType =
|
val installerType =
|
||||||
InstallerType.valueOf(preferences[INSTALLER_TYPE] ?: InstallerType.Default.name)
|
InstallerType.valueOf(preferences[INSTALLER_TYPE] ?: InstallerType.Default.name)
|
||||||
|
val legacyInstallerComponent =
|
||||||
|
preferences[LEGACY_INSTALLER_COMPONENT_CLASS]?.takeIf { it.isNotBlank() }?.let { cls ->
|
||||||
|
preferences[LEGACY_INSTALLER_COMPONENT_ACTIVITY]?.takeIf { it.isNotBlank() }?.let { act ->
|
||||||
|
LegacyInstallerComponent(cls, act)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val language = preferences[LANGUAGE] ?: "system"
|
val language = preferences[LANGUAGE] ?: "system"
|
||||||
val incompatibleVersions = preferences[INCOMPATIBLE_VERSIONS] ?: false
|
val incompatibleVersions = preferences[INCOMPATIBLE_VERSIONS] ?: false
|
||||||
@ -154,6 +171,7 @@ class PreferenceSettingsRepository(
|
|||||||
theme = theme,
|
theme = theme,
|
||||||
dynamicTheme = dynamicTheme,
|
dynamicTheme = dynamicTheme,
|
||||||
installerType = installerType,
|
installerType = installerType,
|
||||||
|
legacyInstallerComponent = legacyInstallerComponent,
|
||||||
autoUpdate = autoUpdate,
|
autoUpdate = autoUpdate,
|
||||||
autoSync = autoSync,
|
autoSync = autoSync,
|
||||||
sortOrder = sortOrder,
|
sortOrder = sortOrder,
|
||||||
@ -185,6 +203,8 @@ class PreferenceSettingsRepository(
|
|||||||
val LAST_CLEAN_UP = longPreferencesKey("key_last_clean_up_time")
|
val LAST_CLEAN_UP = longPreferencesKey("key_last_clean_up_time")
|
||||||
val FAVOURITE_APPS = stringSetPreferencesKey("key_favourite_apps")
|
val FAVOURITE_APPS = stringSetPreferencesKey("key_favourite_apps")
|
||||||
val HOME_SCREEN_SWIPING = booleanPreferencesKey("key_home_swiping")
|
val HOME_SCREEN_SWIPING = booleanPreferencesKey("key_home_swiping")
|
||||||
|
val LEGACY_INSTALLER_COMPONENT_CLASS = stringPreferencesKey("key_legacy_installer_component_class")
|
||||||
|
val LEGACY_INSTALLER_COMPONENT_ACTIVITY = stringPreferencesKey("key_legacy_installer_component_activity")
|
||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
val THEME = stringPreferencesKey("key_theme")
|
val THEME = stringPreferencesKey("key_theme")
|
||||||
@ -200,6 +220,8 @@ class PreferenceSettingsRepository(
|
|||||||
set(UNSTABLE_UPDATES, settings.unstableUpdate)
|
set(UNSTABLE_UPDATES, settings.unstableUpdate)
|
||||||
set(THEME, settings.theme.name)
|
set(THEME, settings.theme.name)
|
||||||
set(DYNAMIC_THEME, settings.dynamicTheme)
|
set(DYNAMIC_THEME, settings.dynamicTheme)
|
||||||
|
settings.legacyInstallerComponent?.let { set(LEGACY_INSTALLER_COMPONENT_CLASS, it.clazz) }
|
||||||
|
settings.legacyInstallerComponent?.let { set(LEGACY_INSTALLER_COMPONENT_ACTIVITY, it.activity) }
|
||||||
set(INSTALLER_TYPE, settings.installerType.name)
|
set(INSTALLER_TYPE, settings.installerType.name)
|
||||||
set(AUTO_UPDATE, settings.autoUpdate)
|
set(AUTO_UPDATE, settings.autoUpdate)
|
||||||
set(AUTO_SYNC, settings.autoSync.name)
|
set(AUTO_SYNC, settings.autoSync.name)
|
||||||
|
@ -3,6 +3,7 @@ package com.looker.droidify.datastore
|
|||||||
import androidx.datastore.core.Serializer
|
import androidx.datastore.core.Serializer
|
||||||
import com.looker.droidify.datastore.model.AutoSync
|
import com.looker.droidify.datastore.model.AutoSync
|
||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyPreference
|
import com.looker.droidify.datastore.model.ProxyPreference
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
import com.looker.droidify.datastore.model.Theme
|
import com.looker.droidify.datastore.model.Theme
|
||||||
@ -29,6 +30,7 @@ data class Settings(
|
|||||||
val theme: Theme = Theme.SYSTEM,
|
val theme: Theme = Theme.SYSTEM,
|
||||||
val dynamicTheme: Boolean = false,
|
val dynamicTheme: Boolean = false,
|
||||||
val installerType: InstallerType = InstallerType.Default,
|
val installerType: InstallerType = InstallerType.Default,
|
||||||
|
val legacyInstallerComponent: LegacyInstallerComponent? = null,
|
||||||
val autoUpdate: Boolean = false,
|
val autoUpdate: Boolean = false,
|
||||||
val autoSync: AutoSync = AutoSync.WIFI_ONLY,
|
val autoSync: AutoSync = AutoSync.WIFI_ONLY,
|
||||||
val sortOrder: SortOrder = SortOrder.UPDATED,
|
val sortOrder: SortOrder = SortOrder.UPDATED,
|
||||||
|
@ -3,6 +3,7 @@ package com.looker.droidify.datastore
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.looker.droidify.datastore.model.AutoSync
|
import com.looker.droidify.datastore.model.AutoSync
|
||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyType
|
import com.looker.droidify.datastore.model.ProxyType
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
import com.looker.droidify.datastore.model.Theme
|
import com.looker.droidify.datastore.model.Theme
|
||||||
@ -37,6 +38,8 @@ interface SettingsRepository {
|
|||||||
|
|
||||||
suspend fun setInstallerType(installerType: InstallerType)
|
suspend fun setInstallerType(installerType: InstallerType)
|
||||||
|
|
||||||
|
suspend fun setLegacyInstallerComponent(component: LegacyInstallerComponent?)
|
||||||
|
|
||||||
suspend fun setAutoUpdate(allow: Boolean)
|
suspend fun setAutoUpdate(allow: Boolean)
|
||||||
|
|
||||||
suspend fun setAutoSync(autoSync: AutoSync)
|
suspend fun setAutoSync(autoSync: AutoSync)
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.looker.droidify.datastore.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class LegacyInstallerComponent(
|
||||||
|
val clazz: String,
|
||||||
|
val activity: String,
|
||||||
|
) {
|
||||||
|
fun update(
|
||||||
|
newClazz: String? = null,
|
||||||
|
newActivity: String? = null,
|
||||||
|
): LegacyInstallerComponent = copy(
|
||||||
|
clazz = newClazz ?: clazz,
|
||||||
|
activity = newActivity ?: activity
|
||||||
|
)
|
||||||
|
}
|
@ -32,7 +32,7 @@ import kotlinx.coroutines.sync.withLock
|
|||||||
|
|
||||||
class InstallManager(
|
class InstallManager(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
settingsRepository: SettingsRepository
|
private val settingsRepository: SettingsRepository
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val installItems = Channel<InstallItem>()
|
private val installItems = Channel<InstallItem>()
|
||||||
@ -115,7 +115,7 @@ class InstallManager(
|
|||||||
private suspend fun setInstaller(installerType: InstallerType) {
|
private suspend fun setInstaller(installerType: InstallerType) {
|
||||||
lock.withLock {
|
lock.withLock {
|
||||||
_installer = when (installerType) {
|
_installer = when (installerType) {
|
||||||
InstallerType.LEGACY -> LegacyInstaller(context)
|
InstallerType.LEGACY -> LegacyInstaller(context, settingsRepository)
|
||||||
InstallerType.SESSION -> SessionInstaller(context)
|
InstallerType.SESSION -> SessionInstaller(context)
|
||||||
InstallerType.SHIZUKU -> ShizukuInstaller(context)
|
InstallerType.SHIZUKU -> ShizukuInstaller(context)
|
||||||
InstallerType.ROOT -> RootInstaller(context)
|
InstallerType.ROOT -> RootInstaller(context)
|
||||||
|
@ -1,20 +1,25 @@
|
|||||||
package com.looker.droidify.installer.installers
|
package com.looker.droidify.installer.installers
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.util.AndroidRuntimeException
|
import android.util.AndroidRuntimeException
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import com.looker.droidify.datastore.SettingsRepository
|
||||||
|
import com.looker.droidify.datastore.get
|
||||||
import com.looker.droidify.domain.model.PackageName
|
import com.looker.droidify.domain.model.PackageName
|
||||||
import com.looker.droidify.installer.model.InstallItem
|
import com.looker.droidify.installer.model.InstallItem
|
||||||
import com.looker.droidify.installer.model.InstallState
|
import com.looker.droidify.installer.model.InstallState
|
||||||
import com.looker.droidify.utility.common.SdkCheck
|
import com.looker.droidify.utility.common.SdkCheck
|
||||||
import com.looker.droidify.utility.common.cache.Cache
|
import com.looker.droidify.utility.common.cache.Cache
|
||||||
import com.looker.droidify.utility.common.extension.intent
|
import com.looker.droidify.utility.common.extension.intent
|
||||||
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
class LegacyInstaller(private val context: Context) : Installer {
|
class LegacyInstaller(private val context: Context,
|
||||||
|
private val settingsRepository: SettingsRepository) : Installer {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val APK_MIME = "application/vnd.android.package-archive"
|
private const val APK_MIME = "application/vnd.android.package-archive"
|
||||||
@ -22,30 +27,38 @@ class LegacyInstaller(private val context: Context) : Installer {
|
|||||||
|
|
||||||
override suspend fun install(
|
override suspend fun install(
|
||||||
installItem: InstallItem,
|
installItem: InstallItem,
|
||||||
): InstallState = suspendCancellableCoroutine { cont ->
|
): InstallState {
|
||||||
val installFlag = if (SdkCheck.isNougat) Intent.FLAG_GRANT_READ_URI_PERMISSION else 0
|
val installFlag = if (SdkCheck.isNougat) Intent.FLAG_GRANT_READ_URI_PERMISSION else 0
|
||||||
val fileUri = if (SdkCheck.isNougat) {
|
val fileUri = if (SdkCheck.isNougat) {
|
||||||
Cache.getReleaseUri(
|
Cache.getReleaseUri(context, installItem.installFileName)
|
||||||
context,
|
|
||||||
installItem.installFileName
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Cache.getReleaseFile(context, installItem.installFileName).toUri()
|
Cache.getReleaseFile(context, installItem.installFileName).toUri()
|
||||||
}
|
}
|
||||||
val installIntent = intent(Intent.ACTION_INSTALL_PACKAGE) {
|
|
||||||
|
val comp = settingsRepository.get { legacyInstallerComponent }.firstOrNull()
|
||||||
|
|
||||||
|
return suspendCancellableCoroutine { cont ->
|
||||||
|
val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE).apply {
|
||||||
setDataAndType(fileUri, APK_MIME)
|
setDataAndType(fileUri, APK_MIME)
|
||||||
flags = installFlag
|
flags = installFlag
|
||||||
|
component = comp?.let { ComponentName(it.clazz, it.activity) }
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
context.startActivity(installIntent)
|
context.startActivity(installIntent)
|
||||||
cont.resume(InstallState.Installed)
|
cont.resume(InstallState.Installed)
|
||||||
} catch (e: AndroidRuntimeException) {
|
} catch (e: AndroidRuntimeException) {
|
||||||
installIntent.flags = installFlag or Intent.FLAG_ACTIVITY_NEW_TASK
|
installIntent.flags = installFlag or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
try {
|
||||||
context.startActivity(installIntent)
|
context.startActivity(installIntent)
|
||||||
cont.resume(InstallState.Installed)
|
cont.resume(InstallState.Installed)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
cont.resume(InstallState.Failed)
|
cont.resume(InstallState.Failed)
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
cont.resume(InstallState.Failed)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun uninstall(packageName: PackageName) =
|
override suspend fun uninstall(packageName: PackageName) =
|
||||||
|
@ -2,6 +2,7 @@ package com.looker.droidify.ui.settings
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -36,6 +37,7 @@ import com.looker.droidify.datastore.extension.themeName
|
|||||||
import com.looker.droidify.datastore.extension.toTime
|
import com.looker.droidify.datastore.extension.toTime
|
||||||
import com.looker.droidify.datastore.model.AutoSync
|
import com.looker.droidify.datastore.model.AutoSync
|
||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyType
|
import com.looker.droidify.datastore.model.ProxyType
|
||||||
import com.looker.droidify.datastore.model.Theme
|
import com.looker.droidify.datastore.model.Theme
|
||||||
import com.looker.droidify.utility.common.SdkCheck
|
import com.looker.droidify.utility.common.SdkCheck
|
||||||
@ -53,6 +55,7 @@ import kotlin.time.Duration
|
|||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
import kotlin.time.Duration.Companion.hours
|
import kotlin.time.Duration.Companion.hours
|
||||||
import com.google.android.material.R as MaterialR
|
import com.google.android.material.R as MaterialR
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class SettingsFragment : Fragment() {
|
class SettingsFragment : Fragment() {
|
||||||
@ -230,6 +233,47 @@ class SettingsFragment : Fragment() {
|
|||||||
onClick = { viewModel.setInstaller(requireContext(), it) }
|
onClick = { viewModel.setInstaller(requireContext(), it) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
val pm = requireContext().packageManager
|
||||||
|
legacyInstallerComponent.connect(
|
||||||
|
titleText = getString(R.string.legacyInstallerComponent),
|
||||||
|
setting = viewModel.getSetting { legacyInstallerComponent },
|
||||||
|
map = {
|
||||||
|
it?.let { component ->
|
||||||
|
val appLabel = runCatching {
|
||||||
|
val info = pm.getApplicationInfo(component.clazz, 0)
|
||||||
|
pm.getApplicationLabel(info).toString()
|
||||||
|
}.getOrElse { component.clazz }
|
||||||
|
"$appLabel (${component.activity})"
|
||||||
|
} ?: getString(R.string.unspecified)
|
||||||
|
},
|
||||||
|
) { component, valueToString ->
|
||||||
|
val installerOptions = run {
|
||||||
|
var contentProtocol = "content://"
|
||||||
|
val intent = Intent(Intent.ACTION_INSTALL_PACKAGE).apply {
|
||||||
|
setDataAndType(contentProtocol.toUri(), "application/vnd.android.package-archive")
|
||||||
|
}
|
||||||
|
val activities = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
|
||||||
|
listOf<LegacyInstallerComponent?>(null) + activities.map {
|
||||||
|
LegacyInstallerComponent(
|
||||||
|
clazz = it.activityInfo.packageName,
|
||||||
|
activity = it.activityInfo.name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addSingleCorrectDialog(
|
||||||
|
initialValue = component,
|
||||||
|
values = installerOptions,
|
||||||
|
title = R.string.legacyInstallerComponent,
|
||||||
|
iconRes = R.drawable.ic_apk_install,
|
||||||
|
valueToString = valueToString,
|
||||||
|
onClick = { viewModel.setLegacyInstallerComponentComponent(it) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
incompatibleUpdates.connect(
|
||||||
|
titleText = getString(R.string.incompatible_versions),
|
||||||
|
contentText = getString(R.string.incompatible_versions_summary),
|
||||||
|
setting = viewModel.getInitialSetting { incompatibleVersions },
|
||||||
|
)
|
||||||
proxyType.connect(
|
proxyType.connect(
|
||||||
titleText = getString(R.string.proxy_type),
|
titleText = getString(R.string.proxy_type),
|
||||||
setting = viewModel.getSetting { proxy.type },
|
setting = viewModel.getSetting { proxy.type },
|
||||||
@ -389,6 +433,9 @@ class SettingsFragment : Fragment() {
|
|||||||
proxyHost.root.isVisible = allowProxies
|
proxyHost.root.isVisible = allowProxies
|
||||||
proxyPort.root.isVisible = allowProxies
|
proxyPort.root.isVisible = allowProxies
|
||||||
forceCleanUp.root.isVisible = settings.cleanUpInterval == Duration.INFINITE
|
forceCleanUp.root.isVisible = settings.cleanUpInterval == Duration.INFINITE
|
||||||
|
|
||||||
|
val useLegacyInstaller = settings.installerType == InstallerType.LEGACY
|
||||||
|
legacyInstallerComponent.root.isVisible = useLegacyInstaller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import com.looker.droidify.datastore.model.AutoSync
|
|||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
import com.looker.droidify.datastore.model.InstallerType.ROOT
|
import com.looker.droidify.datastore.model.InstallerType.ROOT
|
||||||
import com.looker.droidify.datastore.model.InstallerType.SHIZUKU
|
import com.looker.droidify.datastore.model.InstallerType.SHIZUKU
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyType
|
import com.looker.droidify.datastore.model.ProxyType
|
||||||
import com.looker.droidify.datastore.model.Theme
|
import com.looker.droidify.datastore.model.Theme
|
||||||
import com.looker.droidify.installer.installers.isMagiskGranted
|
import com.looker.droidify.installer.installers.isMagiskGranted
|
||||||
@ -191,6 +192,12 @@ class SettingsViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setLegacyInstallerComponentComponent(component: LegacyInstallerComponent?) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
settingsRepository.setLegacyInstallerComponent(component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun exportSettings(file: Uri) {
|
fun exportSettings(file: Uri) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
settingsRepository.export(file)
|
settingsRepository.export(file)
|
||||||
|
@ -145,6 +145,9 @@
|
|||||||
<include
|
<include
|
||||||
android:id="@+id/installer"
|
android:id="@+id/installer"
|
||||||
layout="@layout/enum_type" />
|
layout="@layout/enum_type" />
|
||||||
|
<include
|
||||||
|
android:id="@+id/legacy_installer_component"
|
||||||
|
layout="@layout/enum_type" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -103,12 +103,15 @@
|
|||||||
<string name="install">Install</string>
|
<string name="install">Install</string>
|
||||||
<string name="install_types">Installation Types</string>
|
<string name="install_types">Installation Types</string>
|
||||||
<string name="installer">Installer</string>
|
<string name="installer">Installer</string>
|
||||||
|
<string name="legacyInstallerComponent">Legacy Installer Component</string>
|
||||||
|
<string name="unspecified">Unspecified</string>
|
||||||
<string name="insufficient_storage">Insufficient Space</string>
|
<string name="insufficient_storage">Insufficient Space</string>
|
||||||
<string name="insufficient_storage_DESC">There is not enough free space on the device to install this application. Try clearing some space</string>
|
<string name="insufficient_storage_DESC">There is not enough free space on the device to install this application. Try clearing some space</string>
|
||||||
<string name="legacy_installer">Legacy Installer</string>
|
<string name="legacy_installer">Legacy Installer</string>
|
||||||
<string name="session_installer">Session Installer</string>
|
<string name="session_installer">Session Installer</string>
|
||||||
<string name="root_installer">Root Installer</string>
|
<string name="root_installer">Root Installer</string>
|
||||||
<string name="shizuku_installer">Shizuku Installer</string>
|
<string name="shizuku_installer">Shizuku Installer</string>
|
||||||
|
<string name="shizuku_legacy_installer">Shizuku Legacy Installer</string>
|
||||||
<string name="shizuku_not_alive">Shizuku is not running</string>
|
<string name="shizuku_not_alive">Shizuku is not running</string>
|
||||||
<string name="shizuku_not_installed">Shizuku is not installed</string>
|
<string name="shizuku_not_installed">Shizuku is not installed</string>
|
||||||
<string name="installed">Installed</string>
|
<string name="installed">Installed</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user