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:
parent
4ac24fe806
commit
2d3247e4b8
44 changed files with 353 additions and 199 deletions
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 -> {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue