1. Before you begin
The Navigation Architecture Component simplifies implementing navigation, while also helping you visualize your app's navigation flow. The library provides a number of benefits, including:
- Automatic handling of fragment transactions
- Correctly handling up and back by default
- Default behaviors for animations and transitions
- Deep linking as a first class operation
- Implementing navigation UI patterns (like navigation drawers and bottom nav**)** with little additional work
- Type safety when passing information while navigating
- Android Studio tooling for visualizing and editing the navigation flow of an app
What you'll do
In this codelab, you will work with the sample app seen below:
All the activities and fragments have already been created for you. You will use the Navigation Component to connect them and in doing so, implement the following:
- Visual navigation graph
- Navigation by destination and action
- Transition animations
- Menu navigation, bottom navigation, and menu drawer navigation
- Type safe argument passing
- Deep links
Prerequisites
- Basic Kotlin knowledge (this codelab is in Kotlin)
- The latest stable version of Android Studio, and knowledge of how to use it
- Emulator or device running API 19+
2. Getting Started
Get the Code
Clone the navigation codelab from GitHub:
$ git clone https://github.com/android/codelab-android-navigation
Alternatively you can download the repository as a Zip file:
Get the latest stable version of Android Studio
Make sure you are using the latest version of Android Studio. This is required for the Android Studio navigation tooling.
If you need to download a recent version of Android Studio, you can do so here.
Overview of Navigation
The Navigation Component consists of three key parts, working together in harmony. They are:
- Navigation Graph (New XML resource) - This is a resource that contains all navigation-related information in one centralized location. This includes all the places in your app, known as destinations, and possible paths a user could take through your app.
- NavHostFragment (Layout XML view) - This is a special widget you add to your layout. It displays different destinations from your Navigation Graph.
- NavController (Kotlin/Java object) - This is an object that keeps track of the current position within the navigation graph. It orchestrates swapping destination content in the
NavHostFragment
as you move through a navigation graph.
When you navigate, you'll use the NavController object, telling it where you want to go or what path you want to take in your Navigation Graph. The NavController
will then show the appropriate destination in the NavHostFragment.
That's the basic idea. Let's see what this looks like in practice, starting with the new Navigation Graph resource.
3. Introducing the Navigation Graph
Destinations
The Navigation Component introduces the concept of a destination. A destination is any place you can navigate to in your app, usually a fragment or an activity. These are supported out of the box, but you can also make your own custom destination types if needed.
Navigation Graph
A navigation graph is a new resource type that defines all the possible paths a user can take through an app. It shows visually all the destinations that can be reached from a given destination. Android Studio displays the graph in its Navigation Editor. Here's part of the starting navigation graph you'll create for your app:
Exploring the Navigation Editor
- Open
res/navigation/mobile_navigation.xml
- Click Design to go into Design mode:
Here's what you should see:
The navigation graph shows the available destinations. The arrows between the destinations are called actions. You'll learn more about actions later.
- Click on a destination to see its attributes.
- Click on any action, represented by an arrow, to see its attributes.
Anatomy of a navigation XML file
All of the changes you make in the graphical Navigation Editor change the underlying XML file, similar to the way the Layout Editor modifies the layout XML.
Click the Text tab:
You'll see some XML like this:
<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"
app:startDestination="@+id/home_dest">
<!-- ...tags for fragments and activities here -->
</navigation>
Notice:
<navigation>
is the root node of every navigation graph.<navigation>
contains one or more destinations, represented by<activity>
or<fragment>
elements.app:startDestination
is an attribute that specifies the destination that is launched by default when the user first opens the app.
Let's take a look at a fragment destination:
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_one_fragment">
<argument
.../>
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_two_dest">
</action>
</fragment>
Notice:
android:id
defines an ID for the fragment that you can use to reference the destination elsewhere in this XML and your code.android:name
declares the fully qualified class name of the fragment to instantiate when you navigate to that destination.tools:layout
specifies what layout should be shown in the graphical editor.
Some <fragment>
tags also contain <action>
, <argument>,
and <deepLink>
, all of which we'll cover later.
4. Add a Destination to the Navigation Graph
The sample app starts with a few destinations in the graph. In this step, you'll add a brand new destination. You must add a destination to the navigation graph before you can navigate to it.
- Open
res/navigation/mobile_navigation.xml
, and click the Design tab. - Click the New Destination icon, and select "settings_fragment"
The result is a new destination, which renders a preview of the fragment's layout in the design view.
Note that you can also edit the XML file directly to add destinations:
mobile_navigation.xml
<fragment
android:id="@+id/settings_dest"
android:name="com.example.android.codelabs.navigation.SettingsFragment"
android:label="@string/settings"
tools:layout="@layout/settings_fragment" />
5. Using the Navigation Graph to Navigate
Right now you have this awesome navigation graph, but you're not actually using it to navigate.
Activities and Navigation
The Navigation component follows the guidance outlined in the Principles of Navigation. The Principles of Navigation recommend you use activities as entry points for your app. Activities will also contain global navigation, such as the bottom nav,
In comparison, fragments will be the actual destination-specific layouts.
To get this all to work, you need to modify your activity layouts to contain a special widget called a NavHostFragment
. A NavHostFragment
swaps different fragment destinations in and out as you navigate through the navigation graph.
A simple layout supporting navigation similar to the picture above looks like this. An example of this code can be found in res/layout-470dp/navigation_activity.xml
:
<LinearLayout
.../>
<androidx.appcompat.widget.Toolbar
.../>
<fragment
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/mobile_navigation"
app:defaultNavHost="true"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
.../>
</LinearLayout>
Notice:
- This is a layout for an activity. It contains the global navigation, including a bottom nav and a toolbar
android:name="androidx.navigation.fragment.NavHostFragment"
andapp:defaultNavHost="true"
connect the system back button to theNavHostFragment
app:navGraph="@navigation/mobile_navigation"
associates theNavHostFragment
with a navigation graph. This navigation graph specifies all the destinations the user can navigate to, in thisNavHostFragment
.
NavController
Finally, when a user does something like clicking a button, you need to trigger a navigate command. A special class called the NavController
is what triggers the fragment swaps in the NavHostFragment
.
// Command to navigate to flow_step_one_dest
findNavController().navigate(R.id.flow_step_one_dest)
Note that you pass in either a destination or action ID to navigate. These are the IDs defined in the navigation graph XML. This is an example of passing in a destination ID.
NavController
is powerful because when you call methods like navigate()
or popBackStack(),
it translates these commands into the appropriate framework operations based on the type of destination you are navigating to or from. For example, when you call navigate()
with an activity destination, the NavController
calls startActivity()
on your behalf.
There are a few ways to get a NavController
object associated with your NavHostFragment
. In Kotlin, it's recommended you use one of the following extension functions, depending on whether you're calling the navigation command from within a fragment, activity or view:
Navigate to a Destination with NavController
It's your turn to navigate using NavController
. You'll hook up the Navigate To Destination button to navigate to the flow_step_one_dest
destination (which is a destination that is a FlowStepFragment
):
- Open
HomeFragment.kt
- Hook up the
navigate_destination_button
inonViewCreated()
HomeFragment.kt
val button = view.findViewById<Button>(R.id.navigate_destination_button)
button?.setOnClickListener {
findNavController().navigate(R.id.flow_step_one_dest, null)
}
- Run the app and click the Navigate To Destination button. Note that the button navigates to the
flow_step_one_dest
destination.
The click listener code would look like this:
val button = view.findViewById<Button>(R.id.navigate_destination_button)
button?.setOnClickListener(
Navigation.createNavigateOnClickListener(R.id.flow_step_one_dest, null)
)
6. Changing the Navigation Transition
Each navigate()
call has a not very exciting default transition associated with it, as seen below:
The default transition, as well as other attributes associated with the call, can be overridden by including a set of NavOptions
. NavOptions
uses a Builder
pattern which allows you to override and set only the options you need. There's also a ktx DSL for NavOptions, which is what you'll be using.
For animated transitions, you can define XML animation resources in the anim
resource folder and then use those animations for transitions. Some examples are included in the app code:
Add a Custom Transition
Update the code so that pressing the Navigate To Destination button shows a custom transition animation.
- Open
HomeFragment.kt
- Define a
NavOptions
and pass it into thenavigate()
call tonavigate_destination_button
val options = navOptions {
anim {
enter = R.anim.slide_in_right
exit = R.anim.slide_out_left
popEnter = R.anim.slide_in_left
popExit = R.anim.slide_out_right
}
}
view.findViewById<Button>(R.id.navigate_destination_button)?.setOnClickListener {
findNavController().navigate(R.id.flow_step_one_dest, null, options)
}
- Remove the code added in step 5, if it's still there
- Verify that tapping the Navigate To Destination button causes the fragment to slide onto the screen and that pressing back causes it to slide off the screen
7. Navigate using actions
Actions
The navigation system also allows you to navigate via actions. As previously mentioned, the lines shown in the navigation graph are visual representations of actions.
Navigation by actions has the following benefits over navigation by destination:
- You can visualize the navigation paths through your app
- Actions can contain additional associated attributes you can set, such as a transition animation, arguments values, and backstack behavior
- You can use the plugin safe args to navigate, which you'll see shortly
Here's the visual and XML for the action that connects flow_step_one_dest
and flow_step_two_dest
:
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment">
<argument
.../>
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_two_dest">
</action>
</fragment>
<fragment
android:id="@+id/flow_step_two_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment">
<!-- ...removed for simplicity-->
</fragment>
Notice:
- The actions are nested within the destination - this is the destination you will navigate from
- The action includes a destination argument referring to flow_step_two_dest; this is the ID of where you will navigate to
- The ID for the action is "next_action"
Here is another example, of the action connecting flow_step_two_dest
to home_dest
:
<fragment
android:id="@+id/home_dest"
android:name="com.example.android.codelabs.navigation.HomeFragment"
.../>
<fragment
android:id="@+id/flow_step_two_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment">
<argument
.../>
<action
android:id="@+id/next_action"
app:popUpTo="@id/home_dest">
</action>
</fragment>
Notice:
- The same ID next_action is used for the action connecting
flow_step_two_dest
tohome_dest
. You can navigate using the next_action id from eitherflow_step_one_dest
orflow_step_two_dest
. This is an example of how actions can provide a level of abstraction and can navigate you somewhere different depending on context. - The
popUpTo
attribute is used - this action will pop fragments off of the back-stack until you reachhome_dest
Navigate with an Action
Time to hook up the Navigate with Action button so that it lives up to its name!
- Open the
mobile_navigation.xml
file in Design mode - Drag an arrow from
home_dest
toflow_step_one_dest
:
- With the action arrow selected (blue) change the properties of the action so that:
- ID = next_action
- Transition for Enter = slide_in_right
- Transition for Exit = slide_out_left
- Transitions for Pop Enter = slide_in_left
- Transitions for Pop Exit = slide_out_right
- Click the Text tab
Note the newly added next_action
action under the home_dest
destination:
mobile_navigation.xml
<fragment android:id="@+id/home_dest"
...>
<action android:id="@+id/next_action"
app:destination="@+id/flow_step_one"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
- Open
HomeFragment.kt
- Add a click listener to the
navigate_action_button
HomeFragment.kt
view.findViewById<Button>(R.id.navigate_action_button)?.setOnClickListener(
Navigation.createNavigateOnClickListener(R.id.next_action, null)
)
- Verify that tapping the Navigate To Action now navigates to the next screen.
8. Using safe args for navigation
Safe Args
The navigation component has a Gradle plugin, called safe args, that generates simple object and builder classes for type-safe access to arguments specified for destinations and actions.
Safe args allows you to get rid of code like this when passing values between destinations:
val username = arguments?.getString("usernameKey")
And, instead, replace it with code that has generated setters and getters.
val username = args.username
Pass a value using safe args
- Open the project
build.gradle
file and notice the safe args plugin:
build.gradle
dependencies {
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"
//...
}
- Open the
app/build.gradle
file and notice the applied plugin:
app/build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'androidx.navigation.safeargs.kotlin'
android {
//...
}
- Open
mobile_navigation.xml,
and notice how arguments are defined in theflow_step_one_dest
destination.
mobile_navigation.xml
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_one_fragment">
<argument
android:name="flowStepNumber"
app:argType="integer"
android:defaultValue="1"/>
<action...>
</action>
</fragment>
Using the <argument>
tag, safeargs generates a class called FlowStepFragmentArgs
.
Since the XML includes an argument called flowStepNumber
, specified by android:name="flowStepNumber"
, the generated class FlowStepFragmentArgs
will include a variable flowStepNumber
with getters and setters.
- Open
FlowStepFragment.kt
- Comment out the line of code shown below:
FlowStepFragment.kt
// Comment out this line
// val flowStepNumber = arguments?.getInt("flowStepNumber")
This old-style code is not type-safe. It's better to use safe args.
- Update
FlowStepFragment
to use the code generated classFlowStepFragmentArgs
. This will get theFlowStepFragment
arguments in a type-safe manner:
FlowStepFragment.kt
val safeArgs: FlowStepFragmentArgs by navArgs()
val flowStepNumber = safeArgs.flowStepNumber
Safe Args Direction classes
You can also use safe args to navigate in a type safe way, with or without adding arguments. You do this using the generated Directions classes.
Directions classes are generated for every distinct destination with actions. The Directions class includes methods for every action a destination has.
For example, the navigate_action_button
click listener in HomeFragment.kt could be changed to:
HomeFragment.kt
// Note the usage of curly braces since we are defining the click listener lambda
view.findViewById<Button>(R.id.navigate_action_button)?.setOnClickListener {
val flowStepNumberArg = 1
val action = HomeFragmentDirections.nextAction(flowStepNumberArg)
findNavController().navigate(action)
}
HomeFragmentDirections.nextAction(flowStepNumberArg)
9. Navigating using menus, drawers and bottom navigation
NavigationUI and navigation-ui-ktx
The Navigation Components include a NavigationUI
class and the navigation-ui-ktx
kotlin extensions. NavigationUI
has static methods that associate menu items with navigation destinations, and navigation-ui-ktx
is a set of extension functions that do the same. If NavigationUI
finds a menu item with the same ID as a destination on the current graph, it configures the menu item to navigate to that destination.
Using NavigationUI with an Options menu
One of the easiest ways to use NavigationUI is to have it simplify option menu setup. In particular, NavigationUI simplifies handling the onOptionsItemSelected
callback.
- Open MainActivity.kt
Notice how you already have the code for inflating the menu overflow_menu
in onCreateOptionsMenu
- Open
res/menu/overflow_menu.xml
- Update your overflow menu to include the
settings_dest
overflow_menu.xml
<item
android:id="@+id/settings_dest"
android:icon="@drawable/ic_settings"
android:menuCategory="secondary"
android:title="@string/settings" />
- Open
MainActivity.kt
- Have NavigationUI handle
onOptionsItemSelected
with theonNavDestinationSelected
helper method. If the menu item is not meant to navigate, handle withsuper.onOptionsItemSelected
MainActivity.kt
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return item.onNavDestinationSelected(findNavController(R.id.my_nav_host_fragment))
|| super.onOptionsItemSelected(item)
}
- Run your app. You should have a functional ActionBar menu that navigates to the SettingsFragment.
Using NavigationUI to configure Bottom Navigation
The code already contains the XML layout code for implementing bottom navigation, which is why you see the bottom navigation bar. But it doesn't navigate anywhere.
- Open
res/layout/navigation_activity/navigation_activity.xml (h470dp)
and click the Text tab
Notice how the XML layout code for bottom navigation is there and refers to bottom_nav_menu.xml
navigation_activity.xml (h470dp)
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_nav_menu" />
- Open
res/menu/bottom_nav_menu.xml
Notice how there are two items for the bottom navigation and that their ids match the destinations of navigation graph destinations:
bottom_nav_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/home_dest"
android:icon="@drawable/ic_home"
android:title="@string/home" />
<item
android:id="@id/deeplink_dest"
android:icon="@drawable/ic_android"
android:title="@string/deeplink" />
</menu>
Let's make the bottom navigation actually do something using NavigationUI.
- Open
MainActivity.kt
- Implement the
setupBottomNavMenu
method usingsetupWithNavController(bottomNavigationView: BottomNavigationView, navController: NavController)
MainActivity.kt
private fun setupBottomNavMenu(navController: NavController) {
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav_view)
bottomNav?.setupWithNavController(navController)
}
Now your bottom navigation works!
Using NavigationUI to configure a Navigation Drawer
Finally, let's use NavigationUI
to configure the side navigation and navigation drawer, including handling the ActionBar and proper up navigation. You'll see this if you've got a large enough screen or if the screen is too short for bottom navigation.
First observe how the proper layout XML code is already in the app.
- Open both
navigation_activity.xml
andnavigation_activity.xml (w960dp)
Notice how both layouts contain a NavigationView connected to nav_drawer_menu. In the tablet version (w960dp) the NavigationView is always on screen. On smaller devices the NavigationView is nested within a DrawerLayout.
Now to start implementing the NavigationView
navigation.
- Open
MainActivity.kt
- Implement the
setupNavigationMenu
method usingsetupWithNavController(navigationView: NavigationView, navController: NavController)
. Notice how this version of the method takes aNavigationView
and not aBottomNavigationView
.
MainActivity.kt
private fun setupNavigationMenu(navController: NavController) {
val sideNavView = findViewById<NavigationView>(R.id.nav_view)
sideNavView?.setupWithNavController(navController)
}
Now the navigation view menu will show on the screen, but it will not affect the ActionBar.
Setting up the ActionBar
requires creating an instance of AppBarConfiguration
. The purpose of AppBarConfiguration
is to specify the configuration options you want for your toolbars, collapsing toolbars, and action bars. Configuration options include whether the bar must handle a drawer layout and which destinations are considered top-level destinations.
Top-level destinations are the root-level destinations of your app. These destinations do not display an "up" button in the app bar, and they display the drawer icon if the destination uses a drawer layout.
- Create an
AppBarConfiguration
by passing in a set of top-level destination IDs and the drawer layout.
MainActivity.kt
val drawerLayout : DrawerLayout? = findViewById(R.id.drawer_layout)
appBarConfiguration = AppBarConfiguration(
setOf(R.id.home_dest, R.id.deeplink_dest),
drawerLayout)
Now that you have an AppBarConfiguration, you can call NavigationUI.setupActionBarWithNavController
. This will do the following:
- Show a title in the ActionBar based off of the destination's label
- Display the Up button whenever you're not on a top-level destination
- Display a drawer icon (hamburger icon) when you're on a top-level destination
- Implement
setupActionBarWithNavController
MainActivity.kt
private fun setupActionBar(navController: NavController,
appBarConfig : AppBarConfiguration) {
setupActionBarWithNavController(navController, appBarConfig)
}
You should also have NavigationUI handle what happens when the Up button is pressed.
- Override
onSupportNavigationUp
and callNavigationUI.navigateUp
, using the sameAppBarConfiguration
.
MainActivity.kt
override fun onSupportNavigateUp(): Boolean {
return findNavController(R.id.my_nav_host_fragment).navigateUp(appBarConfiguration)
}
- Run your code. If you open the app in split screen, you should have a working navigation drawer. The up icon and the drawer icon should display at the appropriate times and work correctly.
Adding new destinations to a NavigationView
is easy. Once you have the navigation drawer working with up and back navigation, you just need to add the new menu item.
- Open
menu/nav_drawer_menu.xml
- Add a new menu item for
settings_dest
nav_drawer_menu.xml
<item
android:id="@+id/settings_dest"
android:icon="@drawable/ic_settings"
android:title="@string/settings" />
Now your navigation drawers shows the Settings screen as a destination. Good work!
10. Deep Linking to a destination
Deep Links and Navigation
Navigation components also include deep link support. Deep links are a way to jump into the middle of your app's navigation, whether that's from an actual URL link or a pending intent from a notification.
One benefit of using the navigation library to handle deep links is that it ensures users start on the right destination with the appropriate back stack from other entry points such as app widgets, notifications, or web links (covered in the next step).
Navigation provides a NavDeepLinkBuilder
class to construct a PendingIntent
that will take the user to a specific destination.
Add a Deep Link
We'll use the NavDeepLinkBuilder
to hook up an app widget to a destination.
- Open
DeepLinkAppWidgetProvider.kt
- Add a
PendingIntent
constructed withNavDeepLinkBuilder
:
DeepLinkAppWidgetProvider
val args = Bundle()
args.putString("myarg", "From Widget");
val pendingIntent = NavDeepLinkBuilder(context)
.setGraph(R.navigation.mobile_navigation)
.setDestination(R.id.deeplink_dest)
.setArguments(args)
.createPendingIntent()
remoteViews.setOnClickPendingIntent(R.id.deep_link_button, pendingIntent)
Notice:
setGraph
includes the navigation graph.setDestination
specifies where the link goes to.setArguments
includes any arguments you want to pass into your deep link.
- Add the Deep Link widget to your home screen. Tap and hold on the home screen to see option to add widget.
Tap and hold | Scroll down to find widget |
When you're finished, you'll have a deep link widget.
- Tap the widget, and verify that the Android destination opens with the correct argument. It should say "From Widget" at the top since that is the argument you passed in DeepLinkAppWidgetProvider.
- Verify that hitting the back button takes you to the
home_dest
destination.
DeepLink Backstack
The backstack for a deep link is determined using the navigation graph you pass in. If the explicit Activity you've chosen has a parent activity, those parent Activities are also included.
The backstack is generated using the destinations specified with app:startDestination
. In this app we only have one activity and one level of navigation, so the backstack will take you to the home_dest
destination.
More complicated navigation can include nested navigation graphs. The app:startDestination
at each level of the nested graphs determines the backstack. For more information on deep links and nested graphs, check out the Principles of Navigation.
11. Associating a web link with a destination
The <deepLink> element
One of the most common uses of a deep link is to allow a web link to open an activity in your app. Traditionally you would use an intent-filter and associate a URL with the activity you want to open.
The navigation library makes this extremely simple and allows you to map URLs directly to destinations in your navigation graph.
<deepLink>
is an element you can add to a destination in your graph. Each <deepLink>
element has a single required attribute: app:uri
.
In addition to a direct URI match, the following features are supported:
- URIs without a scheme are assumed to be http and https. For example,
www.example.com
will matchhttp://www.example.com
andhttps://www.example.com
. - You can use placeholders in the form of
{placeholder_name}
to match one or more characters. The String value of the placeholder is available in the arguments Bundle which has a key of the same name. For example,http://www.example.com/users/{id}
will matchhttp://www.example.com/users/4
. - You can use the
.*
wildcard to match zero or more characters. - NavController will automatically handle ACTION_VIEW intents and look for matching deep links.
Add a URIbased Deep Link using <deepLink>
In this step, you'll add a deep link to www.example.com.
- Open
mobile_navigation.xml
- Add a
<deepLink>
element to thedeeplink_dest
destination.
mobile_navigation.xml
<fragment
android:id="@+id/deeplink_dest"
android:name="com.example.android.codelabs.navigation.DeepLinkFragment"
android:label="@string/deeplink"
tools:layout="@layout/deeplink_fragment">
<argument
android:name="myarg"
android:defaultValue="Android!"/>
<deepLink app:uri="www.example.com/{myarg}" />
</fragment>
- Open
AndroidManifest.xml
- Add the
nav-graph
tag. This will ensure the appropriate intent filter is generated
AndroidManifest.xml
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<nav-graph android:value="@navigation/mobile_navigation" />
</activity>
- Launch your app using a deep link. There are two ways to do this:
- Use
adb
:
adb shell am start -a android.intent.action.VIEW -d "http://www.example.com/urlTest"
- Navigate via the Google app**.** You should be able to put www.example.com/urlTest in the search bar and the disambiguation window will appear. Select **Navigation codelab**
Opened using the search bar(not in Chrome) | Disambiguation dialog |
Either way, you should see the message "urlTest" on screen. This was passed through to the fragment, from the URL.
12. [Optional] Try navigating on your own
There's one more part of the codelab app for you to experiment with, and that's the shopping cart button.
This is a recap of the skills you've learned during this codelab. This step does not include comments, so try it on your own:
- Create a new fragment class
- Add the fragment as a destination to your navigation graph
- Have the shopping cart icon open up your new fragment class, using NavigationUI to handle the menu.
13. Congratulations!
You're familiar with the basic concepts behind the Navigation component! In this codelab you learned about:
- Navigation graph structure
- NavHostFragment and NavController
- How to navigate to specific destinations
- How to navigate by action
- How to pass arguments between destinations, including using the new safeargs plugin
- Navigating using menus, bottom navs, and navigation drawers
- Navigating via deep link
You can continue to explore with this app or start using navigation in your own app.
There's a lot more to try, including:
- Popping destinations off the backstack (or any backstack manipulations)
- Nested navigation graphs
- Conditional navigation
- Adding support for new destinations
For more about the Navigation Component check out the documentation or the Jetpack Compose Navigation Codelab. If you're interested in learning about other Architecture Components, try the following codelabs:
- Room with a View Codelab (LiveData, ViewModel and Room)
- Android WorkManager Codelab
- Android Paging Codelab
- Android Lifecycle-aware components Codelab (LiveData and ViewModel)