Using Android Navigation Deeplink: An Easy Way to Use Deep Link in Navigation Component on a Big Project
I will demonstrate how to use deep link in Navigation Component on a big project and show some problems you might found during the implementation.

Navigation on Android is now easier than ever before with the Jetpack Navigation Component. This library allows you to implement navigation without the headache of complex navigation, which makes it easier to scale your navigation implementation in large projects. Navigation Component Benefits1. Automates fragment transactions, this can make our code cleaner. 2. Handles back stack 2. Simplified deep linking 3. Safe Args allows you to pass data between screens easily and type-safe 4. Handles transition animations 5. We can handle Drawer and Bottom Navigation easier 6. Centralizes and visualizes navigation
In this article, I will show you my experience and some problems you might found when you use Jetpack Navigation Component in a big project. **Don't reuse fragments in many navigation graphs.**In a big project, you can't avoid reusing a fragment in many Navigation graphs, but you might end up with this error:The error happens when you try to release the project with pro-guards because SafeArgs Plugin will generate classes Args.kt and Directions.kt for all navigation graphs, but pro-guards won't allow you to have duplicate classes.The solution, Nested Graph!When you need to use a fragment in many flows you can create a nested graph and reuse it anywhere. Deep-link is the hero! You can't predict the future requirements of the business, but you can prepare for future change, deep-link in navigation component can make a complicated flow much simpler.
At the beginning of the project, you may have a significantly complicated flow, However, one day the requirements change, and now the app needs to use just a small flow from the significant flow. We could easily copy some part of the flow into the new flow, but we would have duplicate code. The solution is to make the flow smaller using the nested graph as I mentioned before and use the deep link for navigations. Global Action **Global action is one way to access your navigation graphs from everywhere even from a nested graph just like a deep link, however they can't be accessed from another application.Creating deep linksHere is a shopping cart project which has a product listing, shopping cart, payment, history, and more, and the project is also modularized by feature and uses Single Activity Architecture. I am assuming you already know how to set up and create basic navigation graphs. If you don't, you can learn by following Google's code lab. When you create a navigation graph, I recommend creating one deep link for one flow where you can access the flow from anywhere in the project. Then, use the deep link for navigating between pages in your app, as you might need deep links in the future. Create a Listing graph
<?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/navigation_listing"
app:startDestination="@id/listingFragment">
<fragment
android:id="@+id/listingFragment"
android:name="com.him.oozoublog.navcom.listing.ui.listing.ListingFragment"
android:label="fragment_listing"
tools:layout="@layout/fragment_listing">
<deepLink
android:id="@+id/deepLink"
app:uri="myapp://listing" />
</fragment>
......
</navigation>
<em>language-</em>xml
Create a Shopping Cart navigation graph
<?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"
android:id="@+id/navigation_shopping_cart"
app:startDestination="@id/shoppingCartFragment">
<fragment
android:id="@+id/shoppingCartFragment"
android:name="com.him.oozoublog.navcom.shoppingcart.ui.ShoppingCartFragment"
android:label="ShoppingCartFragment">
<deepLink
android:id="@+id/deepLink"
app:uri="myapp://shopping-cart" />
</fragment>
</navigation>
<em>language-</em>xml
Create a History navigation graph
<?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"
android:id="@+id/history_navigation"
app:startDestination="@id/historyFragment">
<fragment
android:id="@+id/historyFragment"
android:name="com.him.oozoublog.navcom.history.ui.HistoryFragment"
android:label="HistoryFragment">
<deepLink
android:id="@+id/deepLink"
app:uri="myapp://history" />
</fragment>
</navigation>
<em>language-</em>xml
Create a Payment navigation graph
<?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"
android:id="@+id/navigation_payment"
app:startDestination="@id/paymentFragment">
<fragment
android:id="@+id/paymentFragment"
android:name="com.him.oozoublog.navcom.payment.ui.PaymentFragment"
android:label="PaymentFragment">
<deepLink
android:id="@+id/deepLink"
app:uri="myapp://payment" />
</fragment>
</navigation>
<em>language-</em>xml
Create the main navigation graphThe main navigation graph is literally nothing but includes all graphs that need to be integrated into the project.
<?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"
android:id="@+id/main_navigation"
app:startDestination="@+id/navigation_listing">
<include app:graph="@navigation/navigation_listing" />
<include app:graph="@navigation/navigation_history" />
<include app:graph="@navigation/navigation_shopping_cart" />
<include app:graph="@navigation/navigation_payment" />
</navigation>
<em>language-</em>xml
Deep-link handler We need a class that contains all the supported deep links and can be accessed anywhere in the project. We also can have custom functions as needed.
object InternalDeepLink {
const val DOMAIN = "myapp://"
const val LISTING = "${DOMAIN}listing"
const val PAYMENT = "${DOMAIN}payment"
const val SHOPPING_CART = "${DOMAIN}shopping-cart"
const val HISTORY = "${DOMAIN}history"
fun makeCustomDeepLink(id: String): String {
return "${DOMAIN}customDeepLink?id=${id}"
}
}
How to use the deep links Using the deep links is very easy. You can navigate to all screens that support deep links like this:
listingViewModel._navigateToShoppingCart.observe(<em>viewLifecycleOwner</em>, <strong>{
</strong>val deepLink = InternalDeepLink.SHOPPING_CART.<em>toUri</em>()
<em>findNavController</em>().navigate(deepLink)
<strong>}</strong>)
We can use enums in the deep links **Navigation library allows you to pass your custom enum class between destinations, you can view supported argument types.For example, the listing page can search by car, watch, and both.
enum class SearchType {
ALL,
CAR,
WATCH
}
Add an argument into the listing graph
<?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/navigation_listing"
app:startDestination="@id/listingFragment">
<fragment
android:id="@+id/listingFragment"
android:name="com.him.oozoublog.navcom.listing.ui.listing.ListingFragment"
android:label="fragment_listing"
tools:layout="@layout/fragment_listing">
<argument
android:name="searchType"
android:defaultValue="ALL"
app:argType="com.him.oozoublog.navcom.listing.ui.listing.SearchType" />
<deepLink
android:id="@+id/deepLink"
app:uri="myapp://listing?searchType={searchType}" />
</fragment>
</navigation>
<em>language-</em>xml
**How to get the data from deep links.**When we navigate to another page with some data SafeArgs Plugin will automatically handle the data. When you rebuild the project you will see ListingFragmentArgs.kt. This plugin also converts the data to your custom class if there is any. You can use navArgs() delegate for passing data like this:
class ListingFragment : Fragment() {
....
private val args: ListingFragmentArgs by <em>navArgs</em>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.i("search type", args.searchType.name)
}
....
}
Introduction to Deep Links
Deep links are a powerful tool in Android development that can significantly enhance the user experience within your app. Essentially, deep links are unique URLs that direct users to a specific location within the app, bypassing the need to navigate through multiple screens. When used in conjunction with the Navigation Component, deep links simplify in-app navigation, making it more intuitive and efficient for users. By implementing deep links, you can ensure that users can quickly access the content they need, improving overall engagement and satisfaction.
Setting Up the Navigation Component
To set up the Navigation Component in your project, you need to add the necessary library dependencies. Open your build.gradle file and include the following dependencies:
dependencies { implementation 'androidx.navigation:navigation-fragment:2.3.5' implementation 'androidx.navigation:navigation-ui:2.3.5' }
Next, you need to create a navigation graph, which serves as a centralized resource file containing all navigation-related information. To create a navigation graph, add a new resource file to your project and define the destinations and actions within it. This graph will help you manage and visualize the navigation flow in your app, making it easier to implement and maintain.
Creating and Handling Deep Link
Creating a deep link involves adding a deep link element to your navigation graph. This element specifies the destination that the deep link should navigate to. To add a deep link, click on the desired destination in the navigation graph and select “Add deep link” from the context menu. Define the URI for the deep link, ensuring it points to the correct destination.
Handling a deep link requires overriding the onNewIntent method in your activity. Within this method, call handleDeepLink on the Navigation Component to navigate to the specified destination:
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Navigation.findNavController(this, R.id.nav_host_fragment).handleDeepLink(intent); }
By following these steps, you can create and handle deep links effectively, ensuring smooth navigation within your app.
Best Practices for the Navigation Component
When using the Navigation Component, consider the following best practices to optimize your implementation:
- Use a Single Navigation Graph: Maintain a single navigation graph for your entire app to centralize navigation logic and simplify management.
- Prefer Fragments Over Activities: Use fragments as destinations instead of activities to leverage the benefits of the Navigation Component.
- Utilize NavController: Navigate between destinations using the NavController to ensure consistent and predictable navigation behavior.
- Leverage NavigationUI: Use NavigationUI to handle navigation-related UI elements, such as the navigation drawer and bottom navigation.
- Thoroughly Test Your Navigation Graph: Regularly test your navigation graph to ensure it functions as expected and provides a seamless user experience.
By adhering to these best practices, you can make the most of the Navigation Component and create a robust navigation system for your app.
Testing and Troubleshooting Deep Links
Testing deep links is crucial to ensure they work correctly. You can use the adb tool to simulate a deep link URL. For example, to test a deep link, run the following command: adb shell am start -n com.example.myapp/.MainActivity -d "http://example.com/deeplink" To troubleshoot deep links, utilize the Logcat tool to view navigation-related logs. This can help you identify and resolve any issues. Additionally, the Navigation Component debug tool allows you to visualize the navigation graph, making it easier to spot and fix problems.
By following these testing and troubleshooting methods, you can ensure that your deep links function correctly and provide a seamless user experience.That does it - this is how easy it is to use the deep links in Navigation Component for handling your deep link in your app. Share if you have any other ideas - you can find the source code on Github. References: **- https://developer.android.com/guide/navigation- https://proandroiddev.com/scalable-architecture-for-big-mobile-projects-c48f329a2275- https://medium.com/@yuri.live/scalability-and-maintainability-of-mobile-and-other-applications-part-1-21e3d07dadeb- https://medium.com/@piyushgupta77/android-app-architecture-portable-scalable-reusable-2527af3d870a- https://www.youtube.com/watch?v=Y0Cs2MQxyIs- https://proandroiddev.com/android-navigation-component-fc783c03bb8d


