アクティビティのデスティネーション

ナビゲーション グラフでは、デスティネーションがアクティビティである場合があります。アプリ内のアクティビティは 1 つのみにすることをおすすめしますが、多くの場合、アプリではアプリ内の個別のコンポーネントや画面に対して別々のアクティビティを使用します。このような場合については、アクティビティのデスティネーションを有効に活用できます。

Compose と Kotlin DSL

ナビゲーション グラフへのアクティビティ デスティネーションの追加は、Compose とフラグメントで Kotlin DSL を使用する場合の両方で基本的に同じです。これは、NavGraph を NavHost コンポーザブルに渡すときに、同じ createGraph() ラムダを使用するためです。

詳細については、フラグメントと Kotlin DSL をご覧ください。

XML

activity デスティネーションの作成は、フラグメント デスティネーションの作成と類似しています。ただし、activity デスティネーションの性質は大きく異なります。

デフォルトでは、Navigation ライブラリは NavController を Activity レイアウトにアタッチし、アクティブなナビゲーション グラフのスコープはアクティブな Activity に設定されます。ユーザーが別の Activity に移動した場合は、現在のナビゲーション グラフは対象範囲外になります。つまり、Activity デスティネーションはナビゲーション グラフ内のエンドポイントと見なされます。

アクティビティ デスティネーションを追加するには、デスティネーション Activity に完全修飾クラス名を指定します。

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

この XML は、次の startActivity() の呼び出しと同じです。

Kotlin

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

Java

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

この方法が不適切である場合もあります。たとえば、アクティビティ クラスに対するコンパイル時の依存関係がない場合や、暗黙的インテントで移動するという一定のレベルの間接性が望ましい場合があります。デスティネーション Activity のマニフェスト エントリにある intent-filter によって、Activity デスティネーションを構成する方法が決定されます。

たとえば、次のマニフェスト ファイルについて考えてみます。

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

対応する Activity デスティネーションは、マニフェスト エントリ内のものと一致する action 属性と data 属性で構成する必要があります。

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

targetPackage を現在の applicationId に指定すると、メインアプリを含む現在のアプリへのスコープ設定が制限されます。

特定のアプリをデスティネーションにするケースでは、同じメカニズムを使用できます。次の例では、デスティネーションが、com.example.android.another.app という applicationId のアプリとなるように定義しています。

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

動的な引数

前の例では、固定 URL を使用してデスティネーションに移動していました。追加情報が URL の一部として送信される、動的 URL をサポートする必要がある場合もあります。たとえば、https://example.com?userId=<actual user ID> のような形式の URL のユーザー ID を送信するとします。

この場合、data 属性の代わりに dataPattern を使用します。そうすると、引数を指定して 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>

この例では、Safe Args または Bundle を使用して userId 値を指定できます。

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);

この例では、{userId} を someUser に置き換えて、https://example.com?userId=someUser の URI 値を作成しています。