Search code examples
androidnavigationsplash-screenandroid-architecture-navigation

Deep linking with splash screen and login state


I use Navigation Component. I have app with 2 main parts: 1 splash activity with it's nav_graph 2 main activity with bottom navigation where every menu item has its own nav_graph. The problem is that i cant figure out how to do navigation when notification pops up.

So when notification arrived and user clicked on it, i need: - check if app is open and what screen is open now - if app is closed or in background, through deep link, check at splash activity: if user is logged in - move to main activity (if not provide auth screen) keep navigation on deep link to fragment I need.

Splash graph and one of three memu items graphs

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/splash_graph"
            app:startDestination="@id/splashFragment">

    <fragment android:id="@+id/splashFragment"
              android:name="com.app.app.ui.navigation.fragment.SplashFragment"
              android:label="SplashFragment">

        <action android:id="@+id/action_splashFragment_to_authFragment"
                app:popUpTo="@+id/authFragment"
                app:popUpToInclusive="true"
                app:destination="@id/authFragment"/>

        <action android:id="@+id/action_splashFragment_to_mainActivity"
                app:popUpTo="@+id/mainActivity"
                app:popUpToInclusive="true"
                app:destination="@id/mainActivity" app:launchSingleTop="true"/>
    </fragment>

    <fragment android:id="@+id/authFragment"
              android:name="com.app.app.ui.navigation.fragment.AuthFragment"
              android:label="AuthFragment">

        <action android:id="@+id/action_authFragment_to_mainActivity"
                app:popUpTo="@+id/mainActivity"
                app:popUpToInclusive="true"
                app:destination="@id/mainActivity" app:launchSingleTop="true"/>
    </fragment>

    <activity android:id="@+id/mainActivity"
              android:name="com.app.app.ui.navigation.activity.MainActivity"
              android:label="MainActivity">
        <deepLink android:id="@+id/deepLinkMain" app:uri="com.app.app/"/>
    </activity>


</navigation>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/nextFragment"
            app:startDestination="@id/nxtFragment">

    <fragment android:id="@+id/nxtFragment"
              android:name="com.app.app.ui.navigation.fragment.NextFragment"
              android:label="Next">
        <deepLink
                android:id="@+id/deepLink"
                app:uri="com.app.app/nextFragment{id}"
                android:autoVerify="true"/>
        <argument
                android:name="id"
                app:argType="string"/>
    </fragment>
</navigation>

Solution

  • You can do it using pending intent, suppose you get data payload like below :

    {
          "title":"Title",
          "message":"message test",
          "data":{
                 "meta":{
                    "notificationType":"1",
                     "name":"Rjz"
                        }
                 }
    }
    

    and as per notificationType you have to open specific screen then you can do following :

    sendNotification("msg","title",remoteMessage.data)

    private fun sendNotification(messageBody: String,title: String?,data: MutableMap<String, String>) {
    
        val intent = Intent(this, SplashActivity::class.java)
        intent.putExtra("meta", data["meta"])
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        val pendingIntent = PendingIntent.getActivity(
            this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT
        )
    
        val channelId = getString(R.string.default_notification_channel_id)
        val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
        val notificationBuilder = NotificationCompat.Builder(this, channelId)
    
        notificationBuilder.setSmallIcon(R.drawable.ic_app_logo)
            .setContentTitle(title)
            .setContentText(messageBody)
            .setAutoCancel(true)
            .setStyle(NotificationCompat.BigTextStyle())
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent)
    
        val notificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    
        // Since android Oreo notification channel is needed.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId,
                "Channel human readable title",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
        }
    
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build())
    }
    

    and in splash screen you can check that pending intent data , like this :

    val metaString: String? = if (intent.hasExtra("meta")) {
                    intent.extras.get("meta").toString()
                } else {
                    null
                }
        var gson = Gson()   
        var pushData = gson.fromJson(
                        metaString,
                        YourModel::class.java
                    )       
        if(pushData.notificationType==1){
        NavDeepLinkBuilder(this@SplashActivity)
                .setComponentName(MainActivity::class.java)
                .setGraph(R.navigation.name_of_nav_graph)
                .setDestination(R.id.your_dstination_fragment)
                .setArguments(bundleOf(
                             "name" to pushData.name)
                             ).createTaskStackBuilder().startActivities()
        }
    

    You can also pass argument if you want to pass.

    its an easy way to do in such cases. let me know if you stuck anywhere. enjoy..!!