Search code examples
androidkotlinnavigationandroid-jetpack-compose

How to navigate to a composable via notification in Jetpack Compose


I am trying to navigate user to a screen after clicked on the notification I have sent. There some limited articles about this subject. I tried them but I could not achieve to do the action. My code :

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val navController = rememberNavController()

            NavHost(navController = navController, startDestination = "main") {
                composable("main") {
                    main(this@MainActivity)
                }
                composable("testScreen") {
                    testScreen()
                }
            }

        }
    }
}

@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun main(mainActivity: MainActivity) {
    val postNotificationPermission = rememberPermissionState(permission = Manifest.permission.POST_NOTIFICATIONS)
    val waterNotificationService = WaterNotificationService(mainActivity)


    LaunchedEffect(Unit) {
        if (!postNotificationPermission.status.isGranted) {
            postNotificationPermission.launchPermissionRequest()
        }
    }

    Column {
        Button(onClick = {
            waterNotificationService.showBasicNotification()
        }) {
            Text("SHOW NOTIFICATION")

        }
    }
}

@Composable
fun testScreen() {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("TEST SCREEN WELCOME")
    }
}

manifest :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

    <application
        android:name=".WaterApplication"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.NotificationNavigation"
        tools:targetApi="31">
        <receiver android:name="com.yunusulucay.healthylife.AlarmSetup.AlarmReceiverBreath"/>
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.NotificationNavigation">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".ResultActivity"
            android:parentActivityName=".MainActivity"/>
    </application>

</manifest>

Here I only want to do is after I click button it will show some notification and after I click on that notification I want it to navigate me to testScreen() composable. If you can give me a simple example about this it will be better. Thanks in advance.


Solution

  • You will have to set actionIntent and pendingIntent for notification and then you will have to get intent extras in onCreate or onNewIntent depending on the activity's lifecycle.

    Something like this:

    val activityActionIntent = Intent(context, YourActivity::class.java).apply {
                this.putExtra("testingIntent", true)
                flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
            }
            val pendingIntentFlag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else PendingIntent.FLAG_UPDATE_CURRENT
            val activityActionPendingIntent: PendingIntent = PendingIntent.getActivity(
                context,
                requestCode,
                activityActionIntent,
                pendingIntentFlag
            )
            val nBuilder: NotificationCompat.Builder =
                NotificationCompat.Builder(context, "notificationChannel")
                    .setSmallIcon(logo)
                    .setContentTitle(title)
                    .setContentText(body)
                    .setAutoCancel(true)
                    .setColor(ContextCompat.getColor(context, R.color.black))
                    .setContentIntent(activityActionPendingIntent)
    
            notificationManager.notify(REMINDER_ID, nBuilder.build())
    

    In onCreate:

        setContent {
                val viewModel = hiltViewModel<HomeViewModel>()
                val navigateToTestView = intent.getBooleanExtra("testIntent", false)
                val navController = rememberNavController()
                val startDestination = if(navigateToTestView) "testScreen" else "main"
    
                NavHost(navController = navController, startDestination = startDestination) {
                    composable("main") {
                        main(this@MainActivity, navigateToTestView)
                    }
                    composable("testScreen") {
                        testScreen()
                    }
                }
            }