I'm using Firebase Dynamic links to share a particular product with another user. I'm able to create the product share link. The link is generating fine. I'm detecting the link in my main login activity which is the launcher activity of the app.
The link is also getting detected fine. I have 2 navigation graphs. One for the login process and one for the main app. I've to open a particular fragment in the main graph from the login graph. I'm detecting the link in the login graph and creating a deep link as follows:

navController.createDeepLink()
.setComponentName(MainActivity::class.java)
.setGraph(R.navigation.nav_graph_main)
.setDestination(R.id.storeFragment)
.setArguments(bundle)
.createPendingIntent()
.send()

The problem is that when I open the storeFragment, the app jumps to the home fragment of the nav_graph_main. It doesn't stay at the newFragment. Only for a moment.

My nav_graph_main is below :

<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/nav_graph_main"
    app:startDestination="@id/homeFragment">

...other fragments

 <fragment
        android:id="@+id/storeFragment"
        android:name="in.indiahaat.feature.main.home.store_screen.StoreFragment"
        android:label="fragment_store"
        tools:layout="@layout/fragment_store" >
        <action
            android:id="@+id/action_storeFragment_pop"
            app:popUpTo="@id/storeFragment"
            app:popUpToInclusive="true" />

        <action
            android:id="@+id/storeFragment_to_reportRetailerFragment"
            app:popUpTo="@id/reportRetailerFragment"
            app:destination="@id/reportRetailerFragment" />
    </fragment>

...other fragments

</navigation>

Please post a solution for this as I've been stuck on it for a while now.

1

There are 1 answers

2
Sreehari On BEST ANSWER

I had a similar way of redirecting to different fragment based on a condition. But scenario was different.

I had to redirect to different fragments based on type of user logged in and status of the registration. With child navigation's the same would be possible.

For that I had to send the data/condition to landing fragment. Based on this data redirection could be possible.

Similar approach may be tried for your scenario as well.

NOTE: Although the below did not included Firebase and corresponding dependencies.

<!-- Parent Graph -->
<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/nav_graph"
    app:startDestination="@id/landingFragment">


       <!-- Landing Child Graph -->
       <navigation
        android:id="@+id/landingFragment"
        app:startDestination="@id/dashboardFragment">
        <fragment
            android:id="@+id/dashboardFragment"
            android:name="com.....DashboardFrag"
            tools:layout="@layout/fg_dashboard">

             <argument
                android:name="CONTINUE_REGISTRATION"
                android:defaultValue="false"
                app:argType="boolean" />

             <action
                android:id="@+id/continueRegistration"
                app:destination="@id/registration_graph" />

        </fragment>

        </navigation>

       <!-- Child Graph -->
       <navigation
        android:id="@+id/registration_graph"
        app:startDestination="@id/opRegFragment">

         <fragment
            android:id="@+id/opRegFragment"
            android:name="com.....RegFieldsFragment"
            tools:layout="@layout/fg_registration">

        </fragment>

       </navigation>
</navigation>

Now in the Dashboard Fragment do like below.

class DashboardFrag : BaseFrag {

     private var continueReg: Boolean = false

      override fun onCreate(savedInstanceState: Bundle?) {
        DashboardFragArgs.fromBundle(requireArguments()).apply {
            continueReg = CONTINUEREGISTRATION
        }
        super.onCreate(savedInstanceState)
    }


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

       if (continueReg) {
         registrationContinueAction()
       }

    }
  private fun registrationContinueAction() {

       val action = DashboardFragDirections.continueRegistration()
       findNavController().navigate(action)
  }
}

EDIT 1:

As per your comment, you can move the opening new fragment as part of separate graph as well. With below that should work.

Main nav_graph.xml

<!-- Parent Graph -->
    <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/nav_graph"
        app:startDestination="@id/landingFragment">
    
    
           <!-- Landing Child Graph -->
           <navigation
            android:id="@+id/landingFragment"
            app:startDestination="@id/dashboardFragment">
            <fragment
                android:id="@+id/dashboardFragment"
                android:name="com.....DashboardFrag"
                tools:layout="@layout/fg_dashboard">
    
                 <argument
                    android:name="CONTINUE_REGISTRATION"
                    android:defaultValue="false"
                    app:argType="boolean" />
    
                 <action
                    android:id="@+id/continueRegistration"
                    app:destination="@id/registration_graph" />
    
            </fragment>

            </navigation>
    </navigation>

Now in new graph (sub_nav_graph.xml)

<?xml version="1.0" encoding="utf-8"?>
<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/sub_nav_graph"
            app:startDestination="@id/SubGraphLangingFg">


<fragment android:id="@+id/SubGraphLangingFg"
              android:name="com....SubGraphFirstFg"
              android:label="fragment_landingsub_fg"
              tools:layout="@layout/fragment_landingsub_fg">

    </fragment>

</navigation>

And now , it is better to have a new Activity to handle all the sub fragments under this flow. Again it depends on the requirement and feasibility.

in Manifest.xml , register the new Activity

<activity android:name="com.....ChildGraphLandingActivity" />

And the new Activity would be:

class ChildGraphLandingActivity : AppCompatActivity() {

       override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_subgraph)

    }

}

activity_subgraph.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.....ChildGraphLandingActivity">


    <fragment
            android:id="@+id/fragment_container"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/sub_nav_graph" />
    
</FrameLayout>

Now in the invoking fragment, below should be done.

class DashboardFrag : BaseFrag {

......

private fun registrationContinueAction() {
       //If you are expecting a call back
       startActivityForResult(Intent(context, ChildGraphLandingActivity::class.java)....)

      //If call back is not expected
      startActivity(Intent(context, ChildGraphLandingActivity::class.java))
  }

}