Destinos de actividad

En tu gráfico de navegación, un destino puede ser una actividad. Si bien la práctica recomendada es tener una sola actividad en tu app, las apps suelen usar actividades separadas para distintos componentes o pantallas dentro de una app. Los destinos de actividad pueden ser útiles en esos casos.

DSL de Compose y Kotlin

Agregar un destino de actividad a tu gráfico de navegación es básicamente lo mismo en Compose y cuando se usa el DSL de Kotlin con fragmentos. Esto se debe a que, cuando pasas tu NavGraph al elemento componible NavHost, usas la misma expresión lambda createGraph().

Para obtener más información, consulta Cómo compilar un gráfico de manera programática con el DSL de Kotlin.

XML

Crear un destino de actividad es similar a crear un destino de fragmento. Sin embargo, la naturaleza del destino de una actividad es bastante diferente.

De forma predeterminada, la biblioteca de Navigation adjunta el NavController a un diseño Activity, y el gráfico de navegación activo se define en el Activity activo. Si un usuario navega a un Activity diferente, el gráfico de navegación actual ya no está dentro del alcance. Esto significa que un destino Activity debe considerarse un extremo dentro de un gráfico de navegación.

Para agregar un destino de actividad, especifica el destino Activity con su nombre de clase completamente calificado:

<?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>

Este XML es equivalente a la siguiente llamada a startActivity():

Kotlin

startActivity(Intent(context, DestinationActivity::class.java))

Java

startActivity(new Intent(context, DestinationActivity.class));

Es posible que tengas casos en los que este enfoque no resulte apropiado. Por ejemplo, es posible que no tengas una dependencia en tiempo de compilación de la clase de actividad o que prefieras el nivel de indirección que supone pasar por un intent implícito. El intent-filter de la entrada del manifiesto para el Activity de destino determina cómo debes estructurar el destino Activity.

Por ejemplo, considera el siguiente archivo de manifiesto:

<?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>

El destino Activity correspondiente debe configurarse con los atributos action y data que coincidan con los de la entrada del manifiesto:

<?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>

Especificar targetPackage en el applicationId actual limita el alcance a la aplicación actual, que incluye la app principal.

Puedes usar el mismo mecanismo para los casos en los que desees que una app específica sea el destino. En el siguiente ejemplo, se define como destino una app con un applicationId de 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>

Argumentos dinámicos

En los ejemplos anteriores, se usaron URL fijas a fin de navegar a destinos. Es posible que también debas admitir URLs dinámicas en las que se envíe información adicional como parte de ellas. Por ejemplo, puedes enviar un ID de usuario en una URL con un formato similar a https://example.com?userId=<actual user ID>.

En este caso, en lugar del atributo data, usa dataPattern. Luego, puedes proporcionar argumentos que se reemplacen por marcadores de posición con nombre dentro del valor de dataPattern:

<?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>

En este ejemplo, puedes especificar un valor userId mediante Safe Args o con un 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);

En este ejemplo, se sustituye someUser por {userId} y se crea un valor de URI de https://example.com?userId=someUser.