Navigation Component for Android Part 2: Graphs and Deep Links
In this tutorial you’ll use the Jetpack Navigation component to write an Android app utilizing graphs and deep links to navigate through different screens. By Meng Taing.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Navigation Component for Android Part 2: Graphs and Deep Links
30 mins
- Getting Started
- Adding Dependencies
- Inflating Layout to Fragment in AndroidX
- Building Graphs With the Navigation Component
- Adding NavHostFragment With Navigation Component Graph
- Setting up Navigation Component in MainActivity
- Connecting Toolbar, Drawer and Navigation Controller
- Navigating From Drawer Menu Items
- Navigating From Floating Action Button
- Showing DialogFragment
- ViewModel Across Navigation Graph
- Getting ViewModel in Activity From Navigation Graph
- Getting ViewModel in Fragment From Navigation Graph
- Creating Your First Love Letter
- Building Notification With Explicit Deep Link
- Passing Letter With Safe Args
- Getting Letter From Safe Args
- Seeing What You’ve Sent
- Seeing What You’ve Received
- Nested Graph
- Creating Implicit Deep Link With URI
- Handling Web URL Deep Link
- Where to Go From Here?
Creating Your First Love Letter
Open CreateLetterFragment.kt and replace the declaration of lettersViewModel
with the following code:
private val lettersViewModel: LettersViewModel by navGraphViewModels(R.id.nav_graph)
Once again, it’s the same line to get the instance of the same ViewModel.
In the Create Letter Fragment, you might have noticed there are two option menu items:
- PUSH: Create a local push notification. This mimics the notification the app sends when your recipient receives your letter. In this tutorial, you’ll only send love letters to yourself.
- SEND: Create a web URI for a deep link. The URI is supposed to be embedded in the love letter email. If the recipient also has the Love Letter app installed on his or her phone, when he or she clicks the URI in the email app, the phone should launch the Love Letter app to handle the deep link.
When you click SEND or PUSH, handleSend
gets called. Take a look at handleSend
.
private fun handleSend(toSend: () -> Unit) {
if (lettersViewModel != null && lettersViewModel.hasFullProfile()) {
toSend()
// TODO: navigate to sent fragment
} else {
// TODO: navigate to edit profile fragment
}
hideKeyboard()
}
handleSend
is checking if there is any profile information. It’s making sure the name and email aren’t empty.
If there is profile information, invoke toSend
lambda and navigate to SentFragment. Otherwise, show EditProfileFragment dialog.
Based on this logic, replace the implementation of handleSend
with the following code:
if (lettersViewModel.hasFullProfile()) {
toSend()
findNavController().popBackStack(R.id.inboxFragment, false) //1
findNavController().navigate(R.id.sentFragment) //2
} else {
findNavController().navigate(R.id.editProfileFragment) //3
}
hideKeyboard()
Here’s a breakdown of the code above:
The work around here is to go back to InboxFragment, which is the home fragment, first.
- In a fragment, call
findNavController()
to get the navigation controller. After you’ve done your sent action, exit CreateLetterFragment and go to SentFragment to see what you’ve sent. You can’tpopBackStack
directly to SentFragment because it might not be in the navigation stack.The work around here is to go back to InboxFragment, which is the home fragment, first.
- Here you go to SentFragment from InboxFragment.
- If the app doesn’t have profile information, go to EditProfileFragment.
findNavController()
. Make sure to import the one under androidx.navigation.fragment
.Before you can test the PUSH function, you need to learn about how to generate a push notification with deep link.
Building Notification With Explicit Deep Link
There are two types of deep links:
- Explicit: An explicit deep link is a single instance of a deep link that uses a PendingIntent to take users to a specific location within your app.
- Implicit: An implicit deep link is a URI that refers to a specific destination in an app.
Open NotificationHelper.kt. Examine the code and you’ll find three methods:
-
sendLocalNotification
: GetsnotificationManager
fromcontext
and sends the notification. -
sendLocalNotification
: Builds a notification from the letter object. -
buildPendingIntentFromNavigation
: Builds a pending intent to navigate to specific fragment when notification banner is clicked.
There’s no implementation inside buildPendingIntentFromNavigation
yet. Replace the code inside buildPendingIntentFromNavigation
with the code below:
val bundle = Bundle()
bundle.putString(EXTRA_LETTER, gson.toJson(letter)) //1
return NavDeepLinkBuilder(context) //2
.setGraph(R.navigation.nav_graph) //3
.setDestination(R.id.presentationFragment) //4
.setArguments(bundle) //4
.createPendingIntent() //5
Here you:
- Create the bundle which contains the serialized letter string.
- Use
NavDeepLinkBuilder
to build a pending intent. - Pass in your navigation graph resource id.
- Pass in your fragment ID in navigation graph.
- Generate the pending intent. Done!
Run the app and send your first love letter. Go to the create letter screen from the floating action button. Write a message to your loved one and click the PUSH button.
You should see a push notification on the top of your screen. Clicking the notification won’t work because you haven’t configured the PresentationFragment.
Create another letter and click the SEND button. Observe the Logcat in Android Studio. You’ll see a link like this:
http://www.loveletter.com/letter/%7B%22description%22%3A%22This+is+Romeo.+Long+time+no+see.+How+are+you%3F%22%2C%22from%22%3A%22romeo%40loveletter.com%22%2C%22fromName%22%3A%22Romeo%22%2C%22ps%22%3A%22I+love+you%22%2C%22sentAt%22%3A1565102907743%2C%22title%22%3A%22My+First+Love+Letter%22%2C%22to%22%3A%22juliette%40loveletter.com%22%2C%22uid%22%3A1565102907743%7D
You’ll use this link for the implicit deep link implementation in a later section.
What if you haven’t filled in your profile information? If you already have profile information, click the edit profile button from the drawer header, clear the name and email field and click SAVE.
Now go back to create letter screen, click either the PUSH or SEND button. You’ll see the edit profile dialog! This is really cool because you can reuse the dialog with one line of navigation code.
Passing Letter With Safe Args
Safe Args is a Gradle plugin that generates objects and builder classes for type-safe access to arguments specified for destinations and actions. In other words, it forces you to pass correct and sufficient arguments into the fragment when you navigate to it.
To use Safe Args, open build.gradle under app. Add the following line of code the top of the file:
apply plugin: "androidx.navigation.safeargs.kotlin"
Run Gradle sync in Android Studio again.
Now, you’ll make PresentationFragment require a serialized Letter string as an argument. PresentationFragment converts the serialized Letter string into an object and assigns it to the ViewPager.
Open nav_graph.xml, on Design view, then click the presentationFragment in the graph on the left. On the Attributes panel, you’ll find the Arguments section. Click the + on the right hand side.
Name the argument letter and set its type as String. Click Add. That’s it.
Getting Letter From Safe Args
Open PresentationFragment.kt. Assign lettersViewModel
to the navigation graph ViewModel:
private val lettersViewModel: LettersViewModel by navGraphViewModels(R.id.nav_graph)
Then, add the following line of code right below the line above to get the argument’s object:
private val args: PresentationFragmentArgs by navArgs()
Inside onViewCreated
, under super.onViewCreated(view, savedInstanceState)
, add the following code:
val letter = Gson().fromJson(
args.letter.urlDecode(), //1
Letter::class.java
)
lettersViewModel.saveLetterToInbox(letter) //2
viewPager.adapter = context?.let {
LetterPagerAdapter(
it, letter //3
)
}
Here’s a breakdown of this code:
-
The
args
object contains the letter argument. It’s type isString
. You can go to its declaration to see the code of the generated class.urlDecode()
is aString
extension that decodes the URL-encoded string because the serialized Letter is used as a part of URL. - Save the opened letter to inbox. This mimics the behavior of receiving the letters in the inbox so you can reopen them.
- Pass the Letter object to the ViewPager. The ViewPager presents the letter in three sliding pages.
You’ve setup the PresentationFragment. Now you can PUSH a new letter and open it from a push notification!
Give yourself a pat on the back! :]