feat(PMInstaller): don't relaunch install prompts until result received

This was supposed to fix one type of ROM bug where clicking outside of the install prompt would never return a result to the application. However, the workaround was to keep relaunching the install prompt until the user either actually clicked install or cancel. This apparently is also incorrectly handled by a lot of ROMs and causes the install prompt to keep relaunching, even after pressing the install button.

I don't think there's a good solution, so I'll just remove the relaunching behavior since it's more annoying to the user.
This commit is contained in:
rushiiMachine 2025-02-09 14:03:45 -08:00
parent bb5a38d85f
commit 300952ad21
No known key found for this signature in database
GPG key ID: DCBE5952BB3B6420
2 changed files with 1 additions and 43 deletions

View file

@ -42,7 +42,7 @@ class PMIntentReceiver : BroadcastReceiver() {
private fun handleSessionIntent(context: Context, intent: Intent, sessionId: Int) {
val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)
// Launch the user action intent and forward it to PMResultReceiver to keep relaunching it
// Launch the user action intent
if (status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
@Suppress("DEPRECATION")
val confirmationIntent = intent
@ -51,15 +51,6 @@ class PMIntentReceiver : BroadcastReceiver() {
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
}

View file

@ -6,65 +6,33 @@ import com.aliucord.manager.R
import com.aliucord.manager.installers.InstallerResult
import com.aliucord.manager.installers.UnknownInstallerError
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(
private val sessionId: Int,
private val isUninstall: Boolean,
private val onResult: (InstallerResult) -> Unit,
) : BroadcastReceiver() {
/**
* 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.
*/
private val resultReceived = AtomicBoolean(false)
override fun onReceive(context: Context, intent: Intent) {
if (intent.getIntExtra(EXTRA_SESSION_ID, -1) != sessionId) return
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
// 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 -> {
@ -89,7 +57,6 @@ class PMResultReceiver(
const val ACTION_RECEIVE_RESULT = "com.aliucord.manager.RELAY_PM_RESULT"
const val EXTRA_RESULT = "installerResult"
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.