In your navigation graph, a destination can be an activity. While it is best practice to have a single activity in your app, apps often use separate activities for distinct components or screen within an app. Activity destinations can be useful in such cases.
Compose and Kotlin DSL
Adding an activity destination to your navigation graph is essentially the same
in both Compose and when using the Kotlin DSL with fragments. This is because
when passing your NavGraph
to your NavHost
composable, you use the same
createGraph()
lambda.
For more information, see Fragments and the Kotlin DSL.
XML
Creating an activity destination is similar to creating a fragment destination. However, the nature of an activity destination is quite different.
By default, the Navigation library attaches the NavController
to an
Activity
layout, and the active navigation graph is scoped to the active
Activity
. If a user navigates to a different Activity
, the current
navigation graph is no longer in scope. This means that an Activity
destination should be considered an endpoint within a navigation graph.
To add an activity destination, specify the destination Activity
with its
fully qualified class name:
<?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_graph" app:startDestination="@id/simpleFragment"> <activity android:id="@+id/sampleActivityDestination" android:name="com.example.android.navigation.activity.DestinationActivity" android:label="@string/sampleActivityTitle" /> </navigation>
This XML is equivalent to the following call to startActivity()
:
Kotlin
startActivity(Intent(context, DestinationActivity::class.java))
Java
startActivity(new Intent(context, DestinationActivity.class));
You might have cases where this approach is not appropriate. For example, you
might not have a compile-time dependency on the activity class, or you might
prefer the level of indirection of going through an implicit intent. The
intent-filter
in the manifest entry for the destination Activity
dictates how you need to structure the Activity
destination.
For example, consider the following manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.navigation.activity">
<application>
<activity android:name=".DestinationActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data
android:host="example.com"
android:scheme="https" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
The corresponding Activity
destination needs to be configured with
action
and data
attributes matching those in the manifest entry:
<?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_graph" app:startDestination="@id/simpleFragment"> <activity android:id="@+id/localDestinationActivity" android:label="@string/localActivityTitle" app:action="android.intent.action.VIEW" app:data="https://example.com" app:targetPackage="${applicationId}" /> </navigation>
Specifying targetPackage
to the current applicationId
limits the
scope to the current application, which includes the main app.
The same mechanism can be used for cases where you want a specific app to be the
destination. The following example defines a destination to be an app with an
applicationId
of com.example.android.another.app
.
<?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_graph" app:startDestination="@id/simpleFragment"> <activity android:id="@+id/localDestinationActivity" android:label="@string/localActivityTitle" app:action="android.intent.action.VIEW" app:data="https://example.com" app:targetPackage="com.example.android.another.app" /> </navigation>
Dynamic arguments
The previous examples used fixed URLs to navigate to destinations. You might
also need to support dynamic URLs where additional info is sent as part of the
URL. For example, you might send a user ID in a URL with a format similar to
https://example.com?userId=<actual user ID>
.
In this case, instead of the data
attribute, use dataPattern
.
You can then supply arguments to be substituted for named placeholders within
the dataPattern
value:
<?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_graph" app:startDestination="@id/simpleFragment"> <activity android:id="@+id/localDestinationActivity" android:label="@string/localActivityTitle" app:action="android.intent.action.VIEW" app:dataPattern="https://example.com?userId={userId}" app:targetPackage="com.example.android.another.app"> <argument android:name="userId" app:argType="string" /> </activity> </navigation>
In this example, you can specify a userId
value using either Safe Args
or with a Bundle
:
Kotlin
navController.navigate(
R.id.localDestinationActivity,
bundleOf("userId" to "someUser")
)
Java
Bundle args = new Bundle();
args.putString("userId", "someUser");
navController.navigate(R.id.localDestinationActivity, args);
This example substitutes someUser
for {userId}
and creates a URI value of
https://example.com?userId=someUser
.