feat(PMInstaller): wait for uninstalls & fix PM session lifecycle bugs

- Support waiting for package uninstallation results
- Make DowngradeCheckStep wait for uninstall rather than erroring
- Relaunch PackageInstaller user action intents infinitely until result received (Workaround of bug on some ROMs where dismissing the PI dialog by clicking outside wouldn't invoke the callback with STATUS_FAILURE_ABORTED)
- Make PMIntentReceiver & PMResultReceiver non-exported to keep intents from leaking to other apps
- Handle uncaught exceptions thrown in the aforementioned receivers by returning the result back to the app (or logging) to prevent crashes
This commit is contained in:
rushiiMachine 2024-08-03 21:47:08 -07:00
parent 4ac24fe806
commit 2d3247e4b8
No known key found for this signature in database
GPG key ID: DCBE5952BB3B6420
44 changed files with 353 additions and 199 deletions

View file

@ -29,7 +29,9 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"> android:supportsRtl="true">
<receiver android:name=".installers.pm.PMIntentReceiver" /> <receiver
android:name=".installers.pm.PMIntentReceiver"
android:exported="false" />
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"

View file

@ -7,16 +7,22 @@ import java.io.File
*/ */
interface Installer { interface Installer {
/** /**
* Starts an installation and forgets about it. A toast will be shown when the installation was completed. * Starts an installation and forgets about it. A toast will be shown if the installation completes successfully.
* @param apks All APKs (including any splits) to merge into a single install. * @param apks All APKs (including any splits) to merge into a single install.
* @param silent If this is an update, then the update will occur without user interaction. * @param silent If this is an update, then the update will occur without user interaction.
*/ */
fun install(apks: List<File>, silent: Boolean = true) fun install(apks: List<File>, silent: Boolean = true)
/** /**
* Starts an installation and waits for it to finish with a result. A toast will be shown when the installation was completed. * Starts an installation and waits for it to finish with a result. A toast will be shown for all result states.
* @param apks All APKs (including any splits) to merge into a single install. * @param apks All APKs (including any splits) to merge into a single install.
* @param silent If this is an update, then the update will occur without user interaction. * @param silent If this is an update, then the update will occur without user interaction.
*/ */
suspend fun waitInstall(apks: List<File>, silent: Boolean = true): InstallerResult suspend fun waitInstall(apks: List<File>, silent: Boolean = true): InstallerResult
/**
* Triggers an uninstallation and waits for it to complete with a result. A toast will be shown for all result states.
* @param packageName The package name of the target package.
*/
suspend fun waitUninstall(packageName: String): InstallerResult
} }

View file

@ -1,7 +1,7 @@
package com.aliucord.manager.installers package com.aliucord.manager.installers
import android.content.Context
import android.os.Parcelable import android.os.Parcelable
import androidx.annotation.StringRes
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
/** /**
@ -26,16 +26,16 @@ sealed interface InstallerResult : Parcelable {
* This installation encountered an error and has been aborted. * This installation encountered an error and has been aborted.
* All implementors should implement [Parcelable]. * All implementors should implement [Parcelable].
*/ */
abstract class Error : InstallerResult { abstract class Error : InstallerResult, Parcelable {
/** /**
* Loggable error that should not be shown to the user. * The full internal error representation.
*/ */
abstract val debugReason: String abstract fun getDebugReason(): String
/** /**
* Simplified + translatable user facing errors. * Simplified + translatable user facing reason for the failure.
* If null is returned, then the [getDebugReason] will be used instead.
*/ */
@get:StringRes open fun getLocalizedReason(context: Context): String? = null
abstract val localizedReason: Int
} }
} }

View file

@ -0,0 +1,14 @@
package com.aliucord.manager.installers
import android.content.Context
import com.aliucord.manager.R
import kotlinx.parcelize.Parcelize
@Parcelize
data class UnknownInstallerError(val error: Throwable) : InstallerResult.Error() {
override fun getDebugReason() = error.stackTraceToString()
// No localizations for exceptions, use short message anyway
override fun getLocalizedReason(context: Context) =
error.message ?: context.getString(R.string.install_error_unknown)
}

View file

@ -1,34 +1,34 @@
package com.aliucord.manager.installers.pm package com.aliucord.manager.installers.pm
import android.annotation.SuppressLint import android.app.Application
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.* import android.content.pm.*
import android.content.pm.PackageInstaller.SessionParams import android.content.pm.PackageInstaller.SessionParams
import android.os.Build import android.os.Build
import android.os.Process import android.os.Process
import android.util.Log import android.util.Log
import androidx.core.content.ContextCompat
import com.aliucord.manager.BuildConfig import com.aliucord.manager.BuildConfig
import com.aliucord.manager.installers.Installer import com.aliucord.manager.installers.Installer
import com.aliucord.manager.installers.InstallerResult
import kotlinx.coroutines.suspendCancellableCoroutine
import com.aliucord.manager.util.isMiui import com.aliucord.manager.util.isMiui
import kotlinx.coroutines.suspendCancellableCoroutine
import java.io.File import java.io.File
import kotlin.coroutines.resume
/** /**
* APK installer using the [PackageInstaller] from the system's [PackageManager] service. * APK installer using the [PackageInstaller] from the system's [PackageManager] service.
*/ */
class PMInstaller( class PMInstaller(
val context: Context, private val context: Application,
) : Installer { ) : Installer {
init { private val _packageInstaller = context.packageManager.packageInstaller
val pkgInstaller = context.packageManager.packageInstaller
// Destroy all open sessions that may have not been previously cleaned up init {
for (session in pkgInstaller.mySessions) { // Destroy all open sessions that may have not been previously cleaned up due to fatal errors
Log.d(BuildConfig.TAG, "Deleting PackageInstaller session ${session.sessionId}") for (session in _packageInstaller.mySessions) {
pkgInstaller.abandonSession(session.sessionId) Log.d(BuildConfig.TAG, "Deleting old PackageInstaller session ${session.sessionId}")
_packageInstaller.abandonSession(session.sessionId)
} }
} }
@ -36,29 +36,66 @@ class PMInstaller(
startInstall(createInstallSession(silent), apks, false) startInstall(createInstallSession(silent), apks, false)
} }
override suspend fun waitInstall(apks: List<File>, silent: Boolean): InstallerResult { override suspend fun waitInstall(apks: List<File>, silent: Boolean) = suspendCancellableCoroutine { continuation ->
// Create a new install session
val sessionId = createInstallSession(silent) val sessionId = createInstallSession(silent)
return suspendCancellableCoroutine { continuation -> // This will receive parsed data forwarded by PMIntentReceiver
// This will receive parsed data forwarded by PMIntentReceiver val relayReceiver = PMResultReceiver(
val relayReceiver = PMResultReceiver(sessionId, continuation) sessionId = sessionId,
isUninstall = false,
onResult = { continuation.resume(it) },
)
// Unregister PMResultReceiver when this coroutine finishes ContextCompat.registerReceiver(
// additionally, cancel the install session entirely /* context = */ context,
continuation.invokeOnCancellation { /* receiver = */ relayReceiver,
context.unregisterReceiver(relayReceiver) /* filter = */ PMResultReceiver.intentFilter,
context.packageManager.packageInstaller.abandonSession(sessionId) /* flags = */ ContextCompat.RECEIVER_NOT_EXPORTED,
} )
@SuppressLint("UnspecifiedRegisterReceiverFlag") // Unregister PMResultReceiver when this coroutine finishes or error occurs
if (Build.VERSION.SDK_INT >= 33) { // Additionally, cancel the install session entirely
context.registerReceiver(relayReceiver, relayReceiver.filter, Context.RECEIVER_NOT_EXPORTED) continuation.invokeOnCancellation { error ->
} else { context.unregisterReceiver(relayReceiver)
context.registerReceiver(relayReceiver, relayReceiver.filter) context.packageManager.packageInstaller.abandonSession(sessionId)
}
startInstall(sessionId, apks, relay = true)
} }
startInstall(sessionId, apks, relay = true)
}
override suspend fun waitUninstall(packageName: String) = suspendCancellableCoroutine { continuation ->
val callbackIntent = Intent(context, PMIntentReceiver::class.java)
.putExtra(PMIntentReceiver.EXTRA_SESSION_ID, -1)
.putExtra(PMIntentReceiver.EXTRA_RELAY_ENABLED, true)
val pendingIntent = PendingIntent.getBroadcast(
/* context = */ context,
/* requestCode = */ 0,
/* intent = */ callbackIntent,
/* flags = */ PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
)
// This will receive parsed data forwarded by PMIntentReceiver
val relayReceiver = PMResultReceiver(
sessionId = -1,
isUninstall = true,
onResult = { continuation.resume(it) },
)
ContextCompat.registerReceiver(
/* context = */ context,
/* receiver = */ relayReceiver,
/* filter = */ PMResultReceiver.intentFilter,
/* flags = */ ContextCompat.RECEIVER_NOT_EXPORTED,
)
// Unregister PMResultReceiver when this coroutine is cancelled early
continuation.invokeOnCancellation { error ->
context.unregisterReceiver(relayReceiver)
}
_packageInstaller.uninstall(packageName, pendingIntent.intentSender)
} }
/** /**
@ -70,13 +107,8 @@ class PMInstaller(
val params = SessionParams(SessionParams.MODE_FULL_INSTALL).apply { val params = SessionParams(SessionParams.MODE_FULL_INSTALL).apply {
setInstallLocation(PackageInfo.INSTALL_LOCATION_AUTO) setInstallLocation(PackageInfo.INSTALL_LOCATION_AUTO)
if (Build.VERSION.SDK_INT >= 24) { if (Build.VERSION.SDK_INT >= 24) setOriginatingUid(Process.myUid())
setOriginatingUid(Process.myUid()) if (Build.VERSION.SDK_INT >= 26) setInstallReason(PackageManager.INSTALL_REASON_USER)
}
if (Build.VERSION.SDK_INT >= 26) {
setInstallReason(PackageManager.INSTALL_REASON_USER)
}
if (Build.VERSION.SDK_INT >= 31) { if (Build.VERSION.SDK_INT >= 31) {
setInstallScenario(PackageManager.INSTALL_SCENARIO_FAST) setInstallScenario(PackageManager.INSTALL_SCENARIO_FAST)
@ -87,9 +119,7 @@ class PMInstaller(
} }
} }
if (Build.VERSION.SDK_INT >= 34) { if (Build.VERSION.SDK_INT >= 34) setPackageSource(PackageInstaller.PACKAGE_SOURCE_OTHER)
setPackageSource(PackageInstaller.PACKAGE_SOURCE_OTHER)
}
} }
return context.packageManager.packageInstaller.createSession(params) return context.packageManager.packageInstaller.createSession(params)
@ -99,6 +129,7 @@ class PMInstaller(
* Start a [PackageInstaller] session for installation. * Start a [PackageInstaller] session for installation.
* @param apks The apks to install * @param apks The apks to install
* @param relay Whether to use the [PMResultReceiver] flow. * @param relay Whether to use the [PMResultReceiver] flow.
* @return The [PendingIntent] that was registered to the [PackageInstaller.Session]
*/ */
private fun startInstall(sessionId: Int, apks: List<File>, relay: Boolean) { private fun startInstall(sessionId: Int, apks: List<File>, relay: Boolean) {
val callbackIntent = Intent(context, PMIntentReceiver::class.java) val callbackIntent = Intent(context, PMIntentReceiver::class.java)
@ -112,7 +143,7 @@ class PMInstaller(
/* flags = */ PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, /* flags = */ PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
) )
context.packageManager.packageInstaller.openSession(sessionId).use { session -> _packageInstaller.openSession(sessionId).use { session ->
val bufferSize = 1 * 1024 * 1024 // 1MiB val bufferSize = 1 * 1024 * 1024 // 1MiB
for (apk in apks) { for (apk in apks) {

View file

@ -1,10 +1,10 @@
package com.aliucord.manager.installers.pm package com.aliucord.manager.installers.pm
import android.content.Context
import android.content.pm.PackageInstaller import android.content.pm.PackageInstaller
import android.os.Parcelable import android.os.Parcelable
import com.aliucord.manager.R import com.aliucord.manager.R
import com.aliucord.manager.installers.InstallerResult import com.aliucord.manager.installers.InstallerResult
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
/** /**
@ -13,8 +13,7 @@ import kotlinx.parcelize.Parcelize
*/ */
@Parcelize @Parcelize
data class PMInstallerError(val status: Int) : InstallerResult.Error(), Parcelable { data class PMInstallerError(val status: Int) : InstallerResult.Error(), Parcelable {
@IgnoredOnParcel override fun getDebugReason() = when (status) {
override val debugReason = when (status) {
PackageInstaller.STATUS_FAILURE -> "Unknown failure" PackageInstaller.STATUS_FAILURE -> "Unknown failure"
PackageInstaller.STATUS_FAILURE_BLOCKED -> "Blocked" PackageInstaller.STATUS_FAILURE_BLOCKED -> "Blocked"
PackageInstaller.STATUS_FAILURE_INVALID -> "Invalid package" PackageInstaller.STATUS_FAILURE_INVALID -> "Invalid package"
@ -25,15 +24,18 @@ data class PMInstallerError(val status: Int) : InstallerResult.Error(), Parcelab
else -> "Unknown code ($status)" else -> "Unknown code ($status)"
} }
@IgnoredOnParcel override fun getLocalizedReason(context: Context): String {
override val localizedReason = when (status) { val string = when (status) {
PackageInstaller.STATUS_FAILURE -> R.string.install_error_unknown PackageInstaller.STATUS_FAILURE -> R.string.install_error_unknown
PackageInstaller.STATUS_FAILURE_BLOCKED -> R.string.install_error_blocked PackageInstaller.STATUS_FAILURE_BLOCKED -> R.string.install_error_blocked
PackageInstaller.STATUS_FAILURE_INVALID -> R.string.install_error_invalid PackageInstaller.STATUS_FAILURE_INVALID -> R.string.install_error_invalid
PackageInstaller.STATUS_FAILURE_CONFLICT -> R.string.install_error_conflict PackageInstaller.STATUS_FAILURE_CONFLICT -> R.string.install_error_conflict
PackageInstaller.STATUS_FAILURE_STORAGE -> R.string.install_error_storage PackageInstaller.STATUS_FAILURE_STORAGE -> R.string.install_error_storage
PackageInstaller.STATUS_FAILURE_INCOMPATIBLE -> R.string.install_error_incompatible PackageInstaller.STATUS_FAILURE_INCOMPATIBLE -> R.string.install_error_incompatible
/* PackageInstaller.STATUS_FAILURE_TIMEOUT */ 8 -> R.string.install_error_timeout /* PackageInstaller.STATUS_FAILURE_TIMEOUT */ 8 -> R.string.install_error_timeout
else -> R.string.install_error_unknown else -> R.string.install_error_unknown
}
return context.getString(string)
} }
} }

View file

@ -1,66 +1,97 @@
package com.aliucord.manager.installers.pm package com.aliucord.manager.installers.pm
import android.app.PendingIntent
import android.content.* import android.content.*
import android.content.pm.PackageInstaller import android.content.pm.PackageInstaller
import android.util.Log import android.util.Log
import android.widget.Toast
import com.aliucord.manager.BuildConfig import com.aliucord.manager.BuildConfig
import com.aliucord.manager.R
import com.aliucord.manager.installers.InstallerResult import com.aliucord.manager.installers.InstallerResult
import com.aliucord.manager.util.showToast import com.aliucord.manager.installers.UnknownInstallerError
/**
* This class is used as a callback receiver for [PackageInstaller] events,
* registered as a [PendingIntent]. If [PMIntentReceiver.EXTRA_RELAY_ENABLED] is set to true on
* incoming intents, then the incoming intent will be parsed and relayed as an intent intended for [PMResultReceiver]
* that was registered dynamically with the correct session id, which will handle the relayed result and return
* it as a callback back to the application.
*/
class PMIntentReceiver : BroadcastReceiver() { class PMIntentReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
val realSessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1) val realSessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1)
val expectedSessionId = intent.getIntExtra(EXTRA_SESSION_ID, -2) val expectedSessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1)
if (realSessionId != expectedSessionId) return if (realSessionId != expectedSessionId) return
try {
handleSessionIntent(context, intent, expectedSessionId)
} catch (error: Throwable) {
if (intent.getBooleanExtra(EXTRA_RELAY_ENABLED, false)) {
val relayIntent = Intent(PMResultReceiver.ACTION_RECEIVE_RESULT)
.setPackage(BuildConfig.APPLICATION_ID)
.putExtra(PMResultReceiver.EXTRA_SESSION_ID, expectedSessionId)
.putExtra(PMResultReceiver.EXTRA_RESULT, UnknownInstallerError(error))
context.sendBroadcast(relayIntent)
} else {
Log.e(BuildConfig.TAG, "[PMIntentReceiver] Failed to handle intent", error)
}
}
}
private fun handleSessionIntent(context: Context, intent: Intent, sessionId: Int) {
val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999) val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)
// Launch the user action intent and forward it to PMResultReceiver to keep relaunching it
if (status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
@Suppress("DEPRECATION")
val confirmationIntent = intent
.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)!!
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(confirmationIntent)
if (intent.getBooleanExtra(EXTRA_RELAY_ENABLED, false)) {
val relayIntent = Intent(PMResultReceiver.ACTION_RECEIVE_INTENT)
.setPackage(BuildConfig.APPLICATION_ID)
.putExtra(PMResultReceiver.EXTRA_SESSION_ID, sessionId)
.putExtra(PMResultReceiver.EXTRA_USER_ACTION_INTENT, confirmationIntent)
context.sendBroadcast(relayIntent)
}
return
}
// Handle install result
val installerResult = when (status) { val installerResult = when (status) {
-999 -> { PackageInstaller.STATUS_SUCCESS -> InstallerResult.Success
// Invalid intent PackageInstaller.STATUS_FAILURE_ABORTED -> InstallerResult.Cancelled(systemTriggered = true)
null
}
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
@Suppress("DEPRECATION")
val confirmationIntent = intent
.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)!!
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(confirmationIntent)
null // no result yet
}
PackageInstaller.STATUS_SUCCESS -> {
context.showToast(R.string.installer_success)
InstallerResult.Success
}
PackageInstaller.STATUS_FAILURE_ABORTED -> {
context.showToast(R.string.installer_aborted)
InstallerResult.Cancelled(systemTriggered = true)
}
else -> { else -> {
Log.w(BuildConfig.TAG, "Install failed with error code $status") Log.w(BuildConfig.TAG, "PM failed with error code $status")
if (status <= PackageInstaller.STATUS_SUCCESS) if (status <= PackageInstaller.STATUS_SUCCESS) {
null // Unknown status code (not an error) // Unknown status code (not an error)
else { return
} else {
PMInstallerError(status).also { PMInstallerError(status).also {
context.showToast(it.localizedReason) Toast.makeText(
/* context = */ context,
/* text = */ it.getLocalizedReason(context),
/* duration = */ Toast.LENGTH_LONG
).show()
} }
} }
} }
} }
// Forward result to PMResultReceiver if relaying is enabled and have a real result // Forward result to PMResultReceiver if relaying is enabled and have a real result
if (installerResult != null && intent.getBooleanExtra(EXTRA_RELAY_ENABLED, false)) { if (intent.getBooleanExtra(EXTRA_RELAY_ENABLED, false)) {
val relayIntent = Intent(PMResultReceiver.ACTION_RECEIVE_RESULT) val relayIntent = Intent(PMResultReceiver.ACTION_RECEIVE_RESULT)
.setPackage(BuildConfig.APPLICATION_ID)
.putExtra(PMResultReceiver.EXTRA_SESSION_ID, sessionId)
.putExtra(PMResultReceiver.EXTRA_RESULT, installerResult) .putExtra(PMResultReceiver.EXTRA_RESULT, installerResult)
.putExtra(PMResultReceiver.EXTRA_SESSION_ID, realSessionId)
context.sendBroadcast(relayIntent) context.sendBroadcast(relayIntent)
} }

View file

@ -1,33 +1,102 @@
package com.aliucord.manager.installers.pm package com.aliucord.manager.installers.pm
import android.content.* import android.content.*
import android.content.pm.PackageInstaller
import com.aliucord.manager.R
import com.aliucord.manager.installers.InstallerResult import com.aliucord.manager.installers.InstallerResult
import kotlin.coroutines.Continuation import com.aliucord.manager.installers.UnknownInstallerError
import kotlin.coroutines.resume import com.aliucord.manager.util.showToast
import kotlinx.coroutines.*
import java.util.concurrent.atomic.AtomicBoolean
/**
* This receiver is meant to be registered dynamically in combination with [PMIntentReceiver] in order to
* relay parsed [PackageInstaller] results back to the running application.
* Additionally, it will handle restarting [PackageInstaller] user action intents infinitely until
* we have received a result from the system.
*/
class PMResultReceiver( class PMResultReceiver(
private val sessionId: Int, private val sessionId: Int,
private val continuation: Continuation<InstallerResult>, private val isUninstall: Boolean,
private val onResult: (InstallerResult) -> Unit,
) : BroadcastReceiver() { ) : BroadcastReceiver() {
/** /**
* The intent filter this receiver should be registered with to work properly. * Keep re-launching the user action intent until we have received a result from the PM.
* This is necessary because on some ROMs there is no callback intent sent when the user
* clicks outside of the package installer dialog, forcing us to keep relaunching the dialog
* until the user has clicked one of the buttons, after which the intent has been 'used up' and won't show anymore.
*/ */
val filter = IntentFilter(ACTION_RECEIVE_RESULT) private val resultReceived = AtomicBoolean(false)
@Suppress("DEPRECATION")
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
if (intent.action != ACTION_RECEIVE_RESULT) return
if (intent.getIntExtra(EXTRA_SESSION_ID, -1) != sessionId) return if (intent.getIntExtra(EXTRA_SESSION_ID, -1) != sessionId) return
val result = intent.getParcelableExtra<InstallerResult>(EXTRA_RESULT) try {
when (intent.action) {
ACTION_RECEIVE_INTENT -> handleIntent(context, intent)
ACTION_RECEIVE_RESULT -> handleResult(context, intent)
}
} catch (t: Throwable) {
resultReceived.set(true)
context.unregisterReceiver(this)
onResult(UnknownInstallerError(t))
}
}
private fun handleIntent(context: Context, intent: Intent) {
@Suppress("DEPRECATION")
val confirmationIntent = intent.getParcelableExtra<Intent>(EXTRA_USER_ACTION_INTENT)
?: return ?: return
continuation.resume(result) // No result yet, keep relaunching user action intent
CoroutineScope(Dispatchers.Default).launch {
while (true) {
context.startActivity(confirmationIntent)
delay(1000)
if (resultReceived.get()) break
}
}
}
private fun handleResult(context: Context, intent: Intent) {
@Suppress("DEPRECATION")
val result = intent.getParcelableExtra<InstallerResult>(EXTRA_RESULT) ?: return
resultReceived.set(true)
// Show toast for successful and aborted sessions
when (result) {
InstallerResult.Success -> {
context.showToast(if (!isUninstall) R.string.installer_install_success else R.string.installer_uninstall_success)
}
// The reason we don't do this in PMIntentReceiver is we can't tell whether it was
// an old session that for which `abandonSession(...)` was called
is InstallerResult.Cancelled -> {
context.showToast(if (!isUninstall) R.string.installer_install_aborted else R.string.installer_uninstall_aborted)
}
else -> {}
}
context.unregisterReceiver(this)
onResult(result)
} }
companion object { companion object {
const val ACTION_RECEIVE_INTENT = "com.aliucord.manager.RELAY_PM_INTENT"
const val ACTION_RECEIVE_RESULT = "com.aliucord.manager.RELAY_PM_RESULT" const val ACTION_RECEIVE_RESULT = "com.aliucord.manager.RELAY_PM_RESULT"
const val EXTRA_RESULT = "installerResult" const val EXTRA_RESULT = "installerResult"
const val EXTRA_SESSION_ID = "sessionId" const val EXTRA_SESSION_ID = "sessionId"
const val EXTRA_USER_ACTION_INTENT = "userActionIntent"
/**
* The intent filter this receiver should be registered with to work properly.
*/
val intentFilter = IntentFilter().apply {
addAction(ACTION_RECEIVE_INTENT)
addAction(ACTION_RECEIVE_RESULT)
}
} }
} }

View file

@ -75,7 +75,7 @@ class InstallStep(private val options: PatchOptions) : Step(), KoinComponent {
) )
when (result) { when (result) {
is InstallerResult.Error -> throw Error("Failed to install APKs: ${result.debugReason}") is InstallerResult.Error -> throw Error("Failed to install APKs: ${result.getDebugReason()}")
is InstallerResult.Cancelled -> { is InstallerResult.Cancelled -> {
// The install screen is automatically closed immediately once cleanup finishes // The install screen is automatically closed immediately once cleanup finishes
state = StepState.Skipped state = StepState.Skipped

View file

@ -1,12 +1,14 @@
package com.aliucord.manager.patcher.steps.prepare package com.aliucord.manager.patcher.steps.prepare
import android.content.Context import android.content.Context
import android.content.pm.PackageManager.NameNotFoundException
import com.aliucord.manager.R import com.aliucord.manager.R
import com.aliucord.manager.installers.InstallerResult
import com.aliucord.manager.manager.InstallerManager
import com.aliucord.manager.patcher.StepRunner import com.aliucord.manager.patcher.StepRunner
import com.aliucord.manager.patcher.steps.StepGroup import com.aliucord.manager.patcher.steps.StepGroup
import com.aliucord.manager.patcher.steps.base.Step import com.aliucord.manager.patcher.steps.base.Step
import com.aliucord.manager.patcher.steps.base.StepState import com.aliucord.manager.patcher.steps.base.StepState
import com.aliucord.manager.patcher.util.uninstallApk
import com.aliucord.manager.ui.screens.patchopts.PatchOptions import com.aliucord.manager.ui.screens.patchopts.PatchOptions
import com.aliucord.manager.util.getPackageVersion import com.aliucord.manager.util.getPackageVersion
import com.aliucord.manager.util.showToast import com.aliucord.manager.util.showToast
@ -21,6 +23,7 @@ import org.koin.core.component.inject
*/ */
class DowngradeCheckStep(private val options: PatchOptions) : Step(), KoinComponent { class DowngradeCheckStep(private val options: PatchOptions) : Step(), KoinComponent {
private val context: Context by inject() private val context: Context by inject()
private val installers: InstallerManager by inject()
override val group = StepGroup.Prepare override val group = StepGroup.Prepare
override val localizedName = R.string.patch_step_downgrade_check override val localizedName = R.string.patch_step_downgrade_check
@ -30,7 +33,7 @@ class DowngradeCheckStep(private val options: PatchOptions) : Step(), KoinCompon
context.getPackageVersion(options.packageName) context.getPackageVersion(options.packageName)
} }
// Package is not installed // Package is not installed
catch (_: Throwable) { catch (_: NameNotFoundException) {
state = StepState.Skipped state = StepState.Skipped
return return
} }
@ -38,16 +41,25 @@ class DowngradeCheckStep(private val options: PatchOptions) : Step(), KoinCompon
val targetVersion = container val targetVersion = container
.getStep<FetchInfoStep>() .getStep<FetchInfoStep>()
.data.versionCode.toIntOrNull() .data.versionCode.toIntOrNull()
?: throw IllegalArgumentException("Invalid fetched Aliucord target Discord version") ?: throw IllegalArgumentException("Invalid remote target Discord version")
if (currentVersion > targetVersion) { if (currentVersion > targetVersion) {
context.uninstallApk(options.packageName)
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
context.showToast(R.string.installer_uninstall_new) context.showToast(R.string.installer_uninstall_new)
} }
throw Error("Newer version of Aliucord must be uninstalled prior to installing an older version") when (val result = installers.getActiveInstaller().waitUninstall(options.packageName)) {
is InstallerResult.Error -> throw Error("Failed to uninstall Aliucord: ${result.getDebugReason()}")
is InstallerResult.Cancelled -> {
withContext(Dispatchers.Main) {
context.showToast(R.string.installer_uninstall_new)
}
throw Error("Newer versions of Aliucord must be uninstalled prior to installing an older version")
}
else -> {}
}
} }
} }
} }

View file

@ -1,15 +0,0 @@
package com.aliucord.manager.patcher.util
import android.content.Context
import android.content.Intent
import android.net.Uri
// TODO: move this to PMInstaller
fun Context.uninstallApk(packageName: String) {
val packageURI = Uri.parse("package:$packageName")
val uninstallIntent = Intent(Intent.ACTION_DELETE, packageURI).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
startActivity(uninstallIntent)
}

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Αποτυχία ανάκτησης έκδοσης</string> <string name="version_load_fail">Αποτυχία ανάκτησης έκδοσης</string>
<string name="installer_file_save_success">Αποθηκεύτηκε στο %s</string> <string name="installer_file_save_success">Αποθηκεύτηκε στο %s</string>
<string name="installer_file_save_failed">Απέτυχε η αποθήκευση στο %s</string> <string name="installer_file_save_failed">Απέτυχε η αποθήκευση στο %s</string>
<string name="installer_success">Επιτυχής εγκατάσταση του Aliucord</string> <string name="installer_install_success">Επιτυχής εγκατάσταση του Aliucord</string>
<string name="installer_aborted">Εγκατάλειψη εγκατάστασης Aliucord</string> <string name="installer_install_aborted">Εγκατάλειψη εγκατάστασης Aliucord</string>
<string name="installer_dl_verify_fail">Αποτυχία επαλήθευσης λήψης</string> <string name="installer_dl_verify_fail">Αποτυχία επαλήθευσης λήψης</string>
<string name="installer_uninstall_new">Παρακαλώ απεγκαταστήστε την τρέχουσα έκδοση του Aliucord σας για να συνεχίσετε!</string> <string name="installer_uninstall_new">Παρακαλώ απεγκαταστήστε την τρέχουσα έκδοση του Aliucord σας για να συνεχίσετε!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Error al recuperar la versión</string> <string name="version_load_fail">Error al recuperar la versión</string>
<string name="installer_file_save_success">Guardado como %s</string> <string name="installer_file_save_success">Guardado como %s</string>
<string name="installer_file_save_failed">Error al guardar %s</string> <string name="installer_file_save_failed">Error al guardar %s</string>
<string name="installer_success">Aliucord instalado con éxito</string> <string name="installer_install_success">Aliucord instalado con éxito</string>
<string name="installer_aborted">Se abortó la instalación de Aliucord</string> <string name="installer_install_aborted">Se abortó la instalación de Aliucord</string>
<string name="installer_dl_verify_fail">Error al verificar la descarga</string> <string name="installer_dl_verify_fail">Error al verificar la descarga</string>
<string name="installer_uninstall_new">¡Por favor, desinstala tu versión actual de Aliucord para continuar!</string> <string name="installer_uninstall_new">¡Por favor, desinstala tu versión actual de Aliucord para continuar!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Échec de récupération de la version</string> <string name="version_load_fail">Échec de récupération de la version</string>
<string name="installer_file_save_success">Enregistré dans %s</string> <string name="installer_file_save_success">Enregistré dans %s</string>
<string name="installer_file_save_failed">Échec de l\'enregistrement de %s</string> <string name="installer_file_save_failed">Échec de l\'enregistrement de %s</string>
<string name="installer_success">Aliucord installé avec succès</string> <string name="installer_install_success">Aliucord installé avec succès</string>
<string name="installer_aborted">Installation d\'Aliucord interrompue</string> <string name="installer_install_aborted">Installation d\'Aliucord interrompue</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Veuillez désinstaller votre version actuelle d\'Aliucord pour continuer !</string> <string name="installer_uninstall_new">Veuillez désinstaller votre version actuelle d\'Aliucord pour continuer !</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Gagal untuk mendapatkan versi</string> <string name="version_load_fail">Gagal untuk mendapatkan versi</string>
<string name="installer_file_save_success">Disimpan di %s</string> <string name="installer_file_save_success">Disimpan di %s</string>
<string name="installer_file_save_failed">Gagal untuk menyimpan %s</string> <string name="installer_file_save_failed">Gagal untuk menyimpan %s</string>
<string name="installer_success">Berhasil memasang Aliucord</string> <string name="installer_install_success">Berhasil memasang Aliucord</string>
<string name="installer_aborted">Pemasangan Aliucord dibatalkan</string> <string name="installer_install_aborted">Pemasangan Aliucord dibatalkan</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Silahkan copot versi Aliucord Anda saat ini untuk melanjutkan!</string> <string name="installer_uninstall_new">Silahkan copot versi Aliucord Anda saat ini untuk melanjutkan!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -70,8 +70,8 @@
<string name="version_load_fail">バージョンの取得に失敗しました</string> <string name="version_load_fail">バージョンの取得に失敗しました</string>
<string name="installer_file_save_success">%sに保存しました</string> <string name="installer_file_save_success">%sに保存しました</string>
<string name="installer_file_save_failed">%sの保存に失敗しました</string> <string name="installer_file_save_failed">%sの保存に失敗しました</string>
<string name="installer_success">Aliucordのインストールに成功しました</string> <string name="installer_install_success">Aliucordのインストールに成功しました</string>
<string name="installer_aborted">Aliucordのインストールが中断されました</string> <string name="installer_install_aborted">Aliucordのインストールが中断されました</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">続行するには現在のバージョンのAliucordをアンインストールしてください!</string> <string name="installer_uninstall_new">続行するには現在のバージョンのAliucordをアンインストールしてください!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Aliucord tabıslı ornatıldı</string> <string name="installer_install_success">Aliucord tabıslı ornatıldı</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">버전을 가져오지 못했어요</string> <string name="version_load_fail">버전을 가져오지 못했어요</string>
<string name="installer_file_save_success">%s에 저장했어요</string> <string name="installer_file_save_success">%s에 저장했어요</string>
<string name="installer_file_save_failed">%s을(를) 저장하지 못했어요</string> <string name="installer_file_save_failed">%s을(를) 저장하지 못했어요</string>
<string name="installer_success">Aliucord 설치를 완료했어요</string> <string name="installer_install_success">Aliucord 설치를 완료했어요</string>
<string name="installer_aborted">Aliucord 설치를 중단했어요</string> <string name="installer_install_aborted">Aliucord 설치를 중단했어요</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">계속하려면 Aliucord의 현재 버전을 설치 삭제해 주세요!</string> <string name="installer_uninstall_new">계속하려면 Aliucord의 현재 버전을 설치 삭제해 주세요!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Nie można pobrać wersji</string> <string name="version_load_fail">Nie można pobrać wersji</string>
<string name="installer_file_save_success">Zapisano do %s</string> <string name="installer_file_save_success">Zapisano do %s</string>
<string name="installer_file_save_failed">Nie można zapisać %s</string> <string name="installer_file_save_failed">Nie można zapisać %s</string>
<string name="installer_success">Pomyślnie zainstalowano Aliucord</string> <string name="installer_install_success">Pomyślnie zainstalowano Aliucord</string>
<string name="installer_aborted">Przerwano instalację Aliucord</string> <string name="installer_install_aborted">Przerwano instalację Aliucord</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Odinstaluj aktualną wersję Aliucorda, aby kontynuować!</string> <string name="installer_uninstall_new">Odinstaluj aktualną wersję Aliucorda, aby kontynuować!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Falha ao obter versão</string> <string name="version_load_fail">Falha ao obter versão</string>
<string name="installer_file_save_success">Salvo em %s</string> <string name="installer_file_save_success">Salvo em %s</string>
<string name="installer_file_save_failed">Falha ao salvar %s</string> <string name="installer_file_save_failed">Falha ao salvar %s</string>
<string name="installer_success">Aliucord instalado com sucesso</string> <string name="installer_install_success">Aliucord instalado com sucesso</string>
<string name="installer_aborted">Instalação do Aliucord abortada</string> <string name="installer_install_aborted">Instalação do Aliucord abortada</string>
<string name="installer_dl_verify_fail">Falha ao verificar o download</string> <string name="installer_dl_verify_fail">Falha ao verificar o download</string>
<string name="installer_uninstall_new">Por favor, desinstale a versão atual do Aliucord para continuar!</string> <string name="installer_uninstall_new">Por favor, desinstale a versão atual do Aliucord para continuar!</string>
<string name="installer_minimization_warning">Uma vez que as otimizações da bateria não foram desativadas, minimizar esta tela poderá abortar o processo de instalação!</string> <string name="installer_minimization_warning">Uma vez que as otimizações da bateria não foram desativadas, minimizar esta tela poderá abortar o processo de instalação!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Falha ao recuperar versão</string> <string name="version_load_fail">Falha ao recuperar versão</string>
<string name="installer_file_save_success">Guardado em %s</string> <string name="installer_file_save_success">Guardado em %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">O Aliucord foi instalado com sucesso</string> <string name="installer_install_success">O Aliucord foi instalado com sucesso</string>
<string name="installer_aborted">Abortar a instalação de Aliucord</string> <string name="installer_install_aborted">Abortar a instalação de Aliucord</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Por favor, desinstale a versão atual do Aliucord de modo a continuar o processo!</string> <string name="installer_uninstall_new">Por favor, desinstale a versão atual do Aliucord de modo a continuar o processo!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Не удалось получить версию</string> <string name="version_load_fail">Не удалось получить версию</string>
<string name="installer_file_save_success">Сохранено в %s</string> <string name="installer_file_save_success">Сохранено в %s</string>
<string name="installer_file_save_failed">Не удалось сохранить в %s</string> <string name="installer_file_save_failed">Не удалось сохранить в %s</string>
<string name="installer_success">Aliucord успешно установлен</string> <string name="installer_install_success">Aliucord успешно установлен</string>
<string name="installer_aborted">Установка Aliucord отменена</string> <string name="installer_install_aborted">Установка Aliucord отменена</string>
<string name="installer_dl_verify_fail">Не удалось верифицировать скачивание</string> <string name="installer_dl_verify_fail">Не удалось верифицировать скачивание</string>
<string name="installer_uninstall_new">Пожалуйста, удалите вашу текущую версию Aliucord, чтобы продолжить!</string> <string name="installer_uninstall_new">Пожалуйста, удалите вашу текущую версию Aliucord, чтобы продолжить!</string>
<string name="installer_minimization_warning">Поскольку оптимизация работы аккумулятора не была отключена, сворачивание этого экрана может прервать процесс установки!</string> <string name="installer_minimization_warning">Поскольку оптимизация работы аккумулятора не была отключена, сворачивание этого экрана может прервать процесс установки!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Sürüm alınamadı</string> <string name="version_load_fail">Sürüm alınamadı</string>
<string name="installer_file_save_success">%s\'a Kaydedildi</string> <string name="installer_file_save_success">%s\'a Kaydedildi</string>
<string name="installer_file_save_failed">%s Kaydedilemedi</string> <string name="installer_file_save_failed">%s Kaydedilemedi</string>
<string name="installer_success">Aliucord başarıyla indirildi</string> <string name="installer_install_success">Aliucord başarıyla indirildi</string>
<string name="installer_aborted">Aliucord kurulumu iptal edildi</string> <string name="installer_install_aborted">Aliucord kurulumu iptal edildi</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Devam etmek için şimdiki Aliucord sürümünüzü <string name="installer_uninstall_new">Devam etmek için şimdiki Aliucord sürümünüzü
lütfen silin!</string> lütfen silin!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Failed to retrieve version</string> <string name="version_load_fail">Failed to retrieve version</string>
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Aborted Aliucord installation</string> <string name="installer_install_aborted">Aborted Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">Không truy xuất được phiên bản</string> <string name="version_load_fail">Không truy xuất được phiên bản</string>
<string name="installer_file_save_success">Đã lưu vào %s</string> <string name="installer_file_save_success">Đã lưu vào %s</string>
<string name="installer_file_save_failed">Lưu trữ thất bại %s</string> <string name="installer_file_save_failed">Lưu trữ thất bại %s</string>
<string name="installer_success">Aliucord đã được cài đặt thành công</string> <string name="installer_install_success">Aliucord đã được cài đặt thành công</string>
<string name="installer_aborted">Đã hủy bỏ cài đặt Aliucord</string> <string name="installer_install_aborted">Đã hủy bỏ cài đặt Aliucord</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Vui lòng gỡ cài đặt phiên bản Aliucord hiện tại của bạn để tiếp tục!</string> <string name="installer_uninstall_new">Vui lòng gỡ cài đặt phiên bản Aliucord hiện tại của bạn để tiếp tục!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">獲得版本失敗</string> <string name="version_load_fail">獲得版本失敗</string>
<string name="installer_file_save_success">儲存到 %s</string> <string name="installer_file_save_success">儲存到 %s</string>
<string name="installer_file_save_failed">儲存到 %s 失敗</string> <string name="installer_file_save_failed">儲存到 %s 失敗</string>
<string name="installer_success">成功地安裝 Aliucord</string> <string name="installer_install_success">成功地安裝 Aliucord</string>
<string name="installer_aborted">中斷 Aliucord 安裝</string> <string name="installer_install_aborted">中斷 Aliucord 安裝</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">請解除安裝目前版本的 Aliucord 以繼續!</string> <string name="installer_uninstall_new">請解除安裝目前版本的 Aliucord 以繼續!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -69,8 +69,8 @@
<string name="version_load_fail">獲得版本失敗</string> <string name="version_load_fail">獲得版本失敗</string>
<string name="installer_file_save_success">儲存到 %s</string> <string name="installer_file_save_success">儲存到 %s</string>
<string name="installer_file_save_failed">儲存到 %s 失敗</string> <string name="installer_file_save_failed">儲存到 %s 失敗</string>
<string name="installer_success">成功地安裝 Aliucord</string> <string name="installer_install_success">成功地安裝 Aliucord</string>
<string name="installer_aborted">中斷 Aliucord 安裝</string> <string name="installer_install_aborted">中斷 Aliucord 安裝</string>
<string name="installer_dl_verify_fail">Failed to verify download</string> <string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">請解除安裝目前版本的 Aliucord 以繼續!</string> <string name="installer_uninstall_new">請解除安裝目前版本的 Aliucord 以繼續!</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>

View file

@ -80,19 +80,21 @@
<string name="installer_file_save_success">Saved to %s</string> <string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string> <string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_success">Successfully installed Aliucord</string> <string name="installer_install_success">Successfully installed Aliucord</string>
<string name="installer_aborted">Cancelled Aliucord installation</string> <string name="installer_install_aborted">Cancelled Aliucord installation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string> <string name="installer_uninstall_new">Please uninstall your current version of Aliucord in order to continue!</string>
<string name="installer_uninstall_success">Successfully uninstalled Aliucord</string>
<string name="installer_uninstall_aborted">Cancelled uninstallation</string>
<string name="installer_dl_verify_fail">Failed to verify download</string>
<string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string> <string name="installer_minimization_warning">Since battery optimizations have not been disabled, minimizing this screen may abort the installation process!</string>
<string name="install_error_unknown">Failed to install (Unknown reason)</string> <string name="install_error_unknown">Installer failure (Unknown reason)</string>
<string name="install_error_blocked">Installation was blocked</string> <string name="install_error_blocked">Installation was blocked</string>
<string name="install_error_invalid">One or more APKs were invalid or corrupt</string> <string name="install_error_invalid">One or more APKs were invalid or corrupt</string>
<string name="install_error_conflict">Conflicts with an existing app, usually due to mismatched signatures</string> <string name="install_error_conflict">Conflicts with an existing app, usually due to mismatched signatures</string>
<string name="install_error_storage">Not enough available storage to install</string> <string name="install_error_storage">Not enough available storage to install</string>
<string name="install_error_incompatible">Application is incompatible with this device</string> <string name="install_error_incompatible">Application is incompatible with this device</string>
<string name="install_error_timeout">Installation timed out</string> <string name="install_error_timeout">Installer timed out</string>
<string name="install_group_prepare">Prepare</string> <string name="install_group_prepare">Prepare</string>
<string name="install_group_download">Download dependencies</string> <string name="install_group_download">Download dependencies</string>
@ -100,7 +102,7 @@
<string name="install_group_install">Install APK</string> <string name="install_group_install">Install APK</string>
<string name="patch_step_fetch_kt_version">Fetching target Discord version</string> <string name="patch_step_fetch_kt_version">Fetching target Discord version</string>
<string name="patch_step_downgrade_check">Checking for older installations</string> <string name="patch_step_downgrade_check">Checking for newer installations</string>
<string name="patch_step_dl_kt_apk">Downloading Discord APK</string> <string name="patch_step_dl_kt_apk">Downloading Discord APK</string>
<string name="patch_step_dl_kotlin">Downloading Kotlin Stdlib</string> <string name="patch_step_dl_kotlin">Downloading Kotlin Stdlib</string>
<string name="patch_step_dl_injector">Downloading Aliucord Injector</string> <string name="patch_step_dl_injector">Downloading Aliucord Injector</string>