Navigation and Dynamic Features
- Getting Started
- Why Use Android App Bundles?
- How Dynamic Delivery Works
- How Feature Modules Work
- How Navigation Component Works
- Navigation With Dynamic Feature Modules
- Migration to Dynamic Feature Modules
- Testing Navigation and Dynamic Features
- Including Graphs From Dynamic Features
- Including Subgraphs From Feature Modules
- Smoother Transitions Between Features
- Customize the Progress Fragment
- Non-Blocking Navigation Flow
- Handling the Results of the Installation Attempt
- Where to Go From Here?
At I/O 2018, Google introduced a new publishing format: Android App Bundles. These eliminate the need to publish multiple, large APK files for your app to run well on different devices. With App Bundles, each user gets an APK that’s tailor-made for their specific device.
App Bundles also offer dynamic delivery. This means you don’t have to install the whole app to use it, but divide the app into feature modules. At first, you just install the main module. You then install other modules only when needed.
In this tutorial, you’ll learn to use Dynamic Navigator libraries by refactoring Garden Planner, a single-module app, to use feature modules and dynamic navigation.
Your task is to separate the app into the following feature modules:
- The existing app module.
- An info feature module containing a screen with section details.
- A notes feature module containing screens to add section and garden notes.
There’s also an awesome Jetpack Navigation Controller screencast, which quickly walks you through how to build a navigation graph.
For a start on App bundles check out our Getting Started With Android App Bundles tutorial.
Start by using the Download Materials button at the top or bottom of this page to download everything you’ll need for this project.
Next, open the Garden Planner project in Android Studio 3.5 or later by selecting Open an existing Android Studio project from the Android Studio welcome screen:
Take a moment to get familiar with the app. Build and run and you’ll see the app’s main screen:
The app is a simple garden planner that lets you plan out the layout of your garden. Tap on an empty tile and you’ll get a screen that lets you select what you’d like to plant there:
See the details or edit the selection by tapping on the section again:
Tap on Info to get details about which plant you’ve set for a specific section:
Finally, you can add notes to either the section or the garden in general:
Before you start refactoring the app, take a deeper look at how the new features work.
Why Use Android App Bundles?
While Android App Bundles offer several advantages, they have one major disadvantage: Navigation between screens in modules is more complicated than with standard library modules. Here’s why.
When you use standard library modules, the main module can see them all. This makes using anything from the library modules simple:
With feature modules, the dependencies are reversed. The modules have the main module as a dependent. Additionally, it’s possible that the user hasn’t installed a feature module yet. This makes navigating to screens implemented in feature modules tricky:
Until now, you had two approaches to use:
- Use reflection to access code in the feature module.
- Create a library module with interfaces for dynamic features that acts as a common dependency for base module and feature modules. You then load implementations at runtime with ServiceLoader.
Now, there’s a third, simpler option: Using a Dynamic Navigator library. This enables you to use Navigation Controller to navigate between destinations in feature modules.
How Dynamic Delivery Works
The idea behind dynamic delivery is that the Play Store generates optimized APKs for each user’s device configuration. This has two benefits:
- You upload only one archive on the Play Store, saving time.
- Each user gets an optimized APK when they download the app, which makes the download size smaller.
How does it work? First, you upload the app in the new delivery format, Android App Bundle, which contains all the compiled code and resources for all configurations.
When users download your app, the Play Store uses dynamic delivery to generate optimized APK for their device.
How Feature Modules Work
Another benefit of dynamic delivery is that your app doesn’t have to install all at once. Instead, you break it down into pieces that install on demand.
This is possible thanks to a mechanism in Dynamic Delivery called split APK.
Split APKs are similar to regular APKs, except they contain only a part of your app. Android is able to treat multiple split APKs as a single app. This enables you to break up your app into smaller chunks that download and install when required.
There are three types of split APKs:
- Base APK: Contains code and resources for the app’s base functionality. Downloads when the user first downloads the app.
- Configuration APKs: Hold native libraries and specific screen density, CPU architecture or language resources.
- Dynamic feature APKs: Contain code and resources for a feature of your app from a single feature module. You can customize when and how the feature downloads using Play Core library.
How Navigation Component Works
Jetpack Navigation component consists of three key parts:
- Navigation graph: An XML resource file that contains definitions for all navigation destinations in the app and their connections.
- NavHost implementation: A container that displays destinations you define in navigation graph. Navigation component library provides default NavHostFragment implementation.
- NavController: Manages navigation between destinations within NavHost.
When you navigate through your app, you tell NavController which destination you want to navigate to. NavController then displays the proper destination in the NavHost.
Navigation With Dynamic Feature Modules
Google’s Dynamic Navigator library extends the functionality of Navigation Component by enabling it to navigate to destinations from other feature modules. It does so by providing a new implementation of NavHost interface:
It’s time to add the library to the app!
Open the project-level build.gradle and add the
maven block inside
repositories so that the repository looks like:
This will add the snapshot repository to access the Dynamic Navigator library.
Finally, add the library dependency. Open build.gradle from the app module and add the following under
Now, build and run to see if you get any errors.