Skip to content

Commit

Permalink
feat(PMInstaller): don't relaunch install prompts until result received
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rushiiMachine committed Feb 9, 2025
1 parent bb5a38d commit d79be25
Show file tree
Hide file tree
Showing 2 changed files with 1 addition and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,59 +12,30 @@ 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 -> {
Expand All @@ -89,7 +60,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.
Expand Down

0 comments on commit d79be25

Please sign in to comment.