Search code examples
javaandroidkotlinandroid-architecture-componentsandroid-workmanager

Launch a particular Fragment using Navigation component when tapped on Notification that is sent from WorkManager


I'm sending a daily notification to the user based on a condition from the Worker that is launched using BroadcastReceiver. From Worker I only have context for sending notification.

NotificationCompat.Builder(context, CHANNEL_ID).apply {
    setContentTitle(...)
    setContentText(...)
    setContentIntent(pendingIntent(context)) 
}.build()

How do I create PendingIntent for launching a particular fragment using Navigation component?

I tried this:

fun pendingIntent(context: Context): PendingIntent {
    val navController = NavController(context.applicationContext)
    navController.setGraph(R.navigation.your_navigation)
    return navController.createDeepLink()
        .setDestination(R.id.yourFragment)
        .createPendingIntent()
}

But I get following exceptions:

Caused by: java.lang.RuntimeException: Exception inflating package.name:navigation/your_navigation line 7
        at androidx.navigation.NavInflater.inflate(NavInflater.java:90)
        at androidx.navigation.NavController.setGraph(NavController.java:425)
        at androidx.navigation.NavController.setGraph(NavController.java:407)
        at 
        ......
        at package.name.Worker.doWork(Worker.kt:15)
        at androidx.work.Worker$1.run(Worker.java:85)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
        at java.lang.Thread.run(Thread.java:761) 
Caused by: java.lang.IllegalStateException: Could not find Navigator with name "fragment". You must call NavController.addNavigator() for each navigation type.
        at androidx.navigation.NavigatorProvider.getNavigator(NavigatorProvider.java:98)
        at androidx.navigation.NavInflater.inflate(NavInflater.java:100)
        at androidx.navigation.NavInflater.inflate(NavInflater.java:132)
        at androidx.navigation.NavInflater.inflate(NavInflater.java:81)
        at androidx.navigation.NavController.setGraph(NavController.java:425) 
        at androidx.navigation.NavController.setGraph(NavController.java:407) 
        at package.name.NotificationKt.pendingIntent(Notification.kt:57) 
        at package.name.buildNotificationFor(Notification.kt:50) 
        at package.name.showNotificationFor(Notification.kt:22) 
        at package.name.doWork(Worker.kt:15) 
        at androidx.work.Worker$1.run(Worker.java:85) 

Solution

  • As per the Create an explicit deep link documentation, you should be using the NavDeepLinkBuilder class:

    fun pendingIntent(context: Context): PendingIntent {
        return NavDeepLinkBuilder(context)
           .setGraph(R.navigation.your_navigation)
           .setDestination(R.id.android)
           .createPendingIntent()
    }