https://kotlinlang.org logo
#glance
Title
# glance
r

Racka N

07/11/2022, 8:29 PM
Hello everyone. Anyone here got an idea why I can't launch this PendingIntent for Compose Navigation deeplinking from my Glance widget. I get
android.app.PendingIntent$CanceledException
when I execute the action. PendingIntent code
Copy code
internal fun openDeepLinkPendingIntent(context: Context, uriString: String): PendingIntent? {
    val intent = Intent(
        Intent.ACTION_VIEW,
        uriString.toUri()
    )
    return TaskStackBuilder.create(context).run {
        addNextIntentWithParentStack(intent)
        getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
    }
}
My ActionCallback:
Copy code
class OpenTaskDetailsAction : ActionCallback {
    override suspend fun onRun(context: Context, glanceId: GlanceId, parameters: ActionParameters) {
        val taskId = parameters[PendingTasksWidgetParamKeys.TASK_ID_KEY]
        taskId?.let {
            val pendingIntent = openDeepLinkPendingIntent(context, it)
            println("Pending Intent is present: $pendingIntent")
            pendingIntent?.send()
        }
    }
}
More info: I am not directly passing the MainActivity in the Intent because it lives in a different module from the widgets. So I just registered an intent-filter inside the main app manifest file. Full stacktrace:
Copy code
E/GlanceAppWidget: Error in Glance App Widget
    android.app.PendingIntent$CanceledException
        at android.app.PendingIntent.send(PendingIntent.java:959)
        at android.app.PendingIntent.send(PendingIntent.java:771)
        at work.racka.reluct.widgets.tasks.actions.OpenTaskDetailsAction.onRun(PendingTasksWidgetActions.kt:44)
        at androidx.glance.appwidget.action.RunCallbackAction$Companion.run(RunCallbackAction.kt:44)
        at androidx.glance.appwidget.action.ActionCallbackBroadcastReceiver$onReceive$1.invokeSuspend(ActionCallbackBroadcastReceiver.kt:63)
        at androidx.glance.appwidget.action.ActionCallbackBroadcastReceiver$onReceive$1.invoke(Unknown Source:8)
        at androidx.glance.appwidget.action.ActionCallbackBroadcastReceiver$onReceive$1.invoke(Unknown Source:4)
        at androidx.glance.appwidget.CoroutineBroadcastReceiverKt$goAsync$1.invokeSuspend(CoroutineBroadcastReceiver.kt:45)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Never mind. I didn't properly format my URI.
m

Marcel Pinto

07/18/2022, 8:18 AM
Note, you are doing a launch trampoline here, by using the ActionCallback and then launching the activity. You could directly pass the intent with the URI to the
actionStartActivity(intent)
r

Racka N

07/18/2022, 10:20 AM
I figured that out after looking at the docs and used
actionStartActivity
instead. Though one slight problem with this, it doesn't create synthetic backstacks from a deeplink since we can't use
TaskStackBuilder
with normal activity intents. The end result is that we don't have the expected backstacks, the navigation up (back button at the top bar) that is linked to navController can't pop the stack to go back. Activities are just laid on top of each other, while leaving the main activity created from the launcher intent still active. Unless there's something else I'm missing
m

Marcel Pinto

07/19/2022, 6:02 AM
I don’t remember exactly how but you should be able to recreate the same behavior using some of the Intent flags and taskAffinity for your activities. Check https://developer.android.com/guide/components/activities/tasks-and-back-stack
r

Racka N

07/19/2022, 9:09 AM
After reading this, I can stop multiple tasks and activities being launched over one another. Unfortunately, I still can't mimic what
TaskStackBuilder
does with compose-navigation since with
actionStartActivity
onNewIntent is called on a new instance of the activity and not the activity that's already on the stack even with
FLAG_ACTIVITY_SINGLE_TOP
Ok, just noticed some very strange behavior. Deeplinks to destinations that aren't in a nested graph (defined directly in the root graph instead of being inside
navigation
builder) create the expected backstacks and don't launch a new activity if it's already in the stack. But those inside
navigation
builder exhibit the behavior stated in the previous post. Seems like an issue related to
compose-navigation
and not the Intents. Thank's for help, I'll investigate this further with regards to compose navigation.
m

Marcel Pinto

07/19/2022, 11:01 AM
👍 in the meantime feel free to open a FR in glance to create an action for pending intents. It should be fairly simple to add
14 Views