Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigate to a particular fragment when app launched from sharesheet

I am using Jetpack Navigation in my app having a single activity and two fragments (Fragment A which is also the home fragment and Fragment B which can be navigated from Fragment A).

There is an intent-filter added to the MainActivity as shown below which can accept plain text.

 <activity android:name=".MainActivity"
        android:screenOrientation="portrait">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>

        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="@string/text_mime_type_text_plain"/>
        </intent-filter>
    </activity>

When a user selects my app from the Android sharesheet, the end goal is to pass the data received from the Intent to the Fragment B. Currently, I am receiving the Intent in Fragment A (Home Fragment) and then using NavController to navigate to Fragment B using the below code.

  private fun checkReceivedIntent() {
    val receivedUrlIntent = activity?.intent
    val intentAction = receivedUrlIntent?.action
    val intentType = receivedUrlIntent?.type

    if (intentAction == Intent.ACTION_SEND && intentType != null) {
        if (intentType == getString(R.string.text_mime_type_text_plain) ) {
            val receivedText = receivedUrlIntent.getStringExtra(Intent.EXTRA_TEXT)
            val action = FragmentADirections.actionFragmentAToFragmentB(receivedText)
            findNavController().navigate(action)
        }
    }
}

The problem is that when Fragment B is opened, on pressing the back button or back arrow of Toolbar (Even when pressed multiple times) the Fragment A doesn't appear and Fragment B keeps on reappearing.

I don't know what I am missing. Is this a proper way to open a particular fragment when the app is opened by the user from the share sheet inside another app?

Edit

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">

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

<com.google.android.material.bottomappbar.BottomAppBar
    android:id="@+id/bottomAppBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    app:fabCradleMargin="8dp"

    />

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fabMainActivity"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_add"
    app:layout_anchor="@id/bottomAppBar" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
like image 296
Mehul Kanzariya Avatar asked Nov 06 '19 12:11

Mehul Kanzariya


1 Answers

Why you cannot directly go to Fragment B once received the the Intent Extra in your Activity. Just instead of defining Fragment in the xml, or as a startDestination you could simply perform switch to Fragment B

In the Activity:

       Navigation
            .findNavController(binding.root)
            .navigate(
                R.id.navigation_from_intent_actions, bundle,
                NavOptions.Builder()
                    .setIntentExtra(extras)
                    .build()
            )

UPDATE

To return to previous fragment, you can easily do with getting Fragment from the FragmentManager (it won't be killed, because it's your home Fragment). You can do it in the next way:

  private fun returnWithName() {
      val name = name_input.text.toString()

      (targetFragment as? FragmentA)?.setName(name)
      activity?.supportFragmentManager?
           .popBackStackImmediate()
  }

And later just check updated result from FragmentB. To which Fragment you need to navigate.

Note. There is also another way to share data with Shared ViewModel. However, you would need to transfer result from ViewModel back to FragmentA. And then check for new transaction parameters. It's also described here.

like image 183
GensaGames Avatar answered Oct 08 '22 08:10

GensaGames