Android では、アプリ内の特定のデスティネーションにユーザーを直接誘導するリンクをディープリンクと呼びます。
Navigation コンポーネントを使用すると、「明示的」と「暗黙的」という 2 種類のディープリンクを作成できます。
明示的ディープリンクを作成する
明示的ディープリンクは、PendingIntent
を使用してアプリ内の特定の場所にユーザーを誘導するディープリンクの単一インスタンスです。たとえば、通知やアプリ ウィジェットの一部として明示的ディープリンクを表示できます。
ユーザーが明示的ディープリンクを通じてアプリを開くと、タスク バックスタックがクリアされ、ディープリンク デスティネーションに置き換えられます。グラフをネストしている場合は、各ネストレベルの開始デスティネーション(つまり、階層内の各 <navigation>
要素の開始デスティネーション)もスタックに追加されます。そのため、ユーザーがディープリンク デスティネーションから [戻る] ボタンを押すと、アプリにそのエントリ ポイントからアクセスしたかのようにナビゲーション スタックを戻ることができます。
以下の例に示すように、NavDeepLinkBuilder
クラスを使用して、PendingIntent
を作成できます。指定されたコンテキストが Activity
でない場合、コンストラクタは、起動するデフォルト アクティビティとして PackageManager.getLaunchIntentForPackage()
を使用します(利用可能な場合)。
Kotlin
val pendingIntent = NavDeepLinkBuilder(context) .setGraph(R.navigation.nav_graph) .setDestination(R.id.android) .setArguments(args) .createPendingIntent()
Java
PendingIntent pendingIntent = new NavDeepLinkBuilder(context) .setGraph(R.navigation.nav_graph) .setDestination(R.id.android) .setArguments(args) .createPendingIntent();
デフォルトでは、NavDeepLinkBuilder
はアプリのマニフェストに宣言されたデフォルト起動 Activity
への明示的ディープリンクを起動します。NavHost
が別のアクティビティにある場合は、ディープリンク ビルダーを作成する際に、次のようにしてそのコンポーネント名を指定する必要があります。
Kotlin
val pendingIntent = NavDeepLinkBuilder(context) .setGraph(R.navigation.nav_graph) .setDestination(R.id.android) .setArguments(args) .setComponentName(DestinationActivity::class.java) .createPendingIntent()
Java
PendingIntent pendingIntent = new NavDeepLinkBuilder(context) .setGraph(R.navigation.nav_graph) .setDestination(R.id.android) .setArguments(args) .setComponentName(DestinationActivity.class) .createPendingIntent();
ComponentName
がある場合は、次のようにビルダーにそのまま渡すことができます。
Kotlin
val componentName = ... val pendingIntent = NavDeepLinkBuilder(context) .setGraph(R.navigation.nav_graph) .setDestination(R.id.android) .setArguments(args) .setComponentName(componentName) .createPendingIntent()
Java
ComponentName componentName = ...; PendingIntent pendingIntent = new NavDeepLinkBuilder(context) .setGraph(R.navigation.nav_graph) .setDestination(R.id.android) .setArguments(args) .setComponentName(componentName) .createPendingIntent();
既存の NavController
がある場合は、NavController.createDeepLink()
を使用してディープリンクを作成することもできます。
暗黙的ディープリンクを作成する
暗黙的ディープリンクは、アプリ内の特定のデスティネーションを参照します。ディープリンクが呼び出されると(たとえばユーザーがリンクをタップしたとき)、Android は対応するデスティネーションでアプリを開くことができます。
ディープリンクは、URI、インテント アクション、MIME タイプによってマッチングできます。単一のディープリンクに対して複数のマッチタイプを指定できますが、マッチングの優先順位は URI 引数、アクション、MIME タイプの順になります。
URI、アクション、MIME タイプを含むディープリンクの例を次に示します。
<fragment android:id="@+id/a"
android:name="com.example.myapplication.FragmentA"
tools:layout="@layout/a">
<deepLink app:uri="www.example.com"
app:action="android.intent.action.MY_ACTION"
app:mimeType="type/subtype"/>
</fragment>
Navigation Editor を使用して、デスティネーションへの暗黙的ディープリンクを作成することもできます。手順は次のとおりです。
- Navigation Editor の [Design] タブで、ディープリンクのデスティネーションを選択します。
- [Attributes] パネルの [Deep Links] セクションで、[+] をクリックします。
表示された [Add Deep Link] ダイアログで、ディープリンクの情報を入力します。
次の点に注意してください。
- スキーマのない URI は、http または https のいずれかと見なされます。たとえば、
www.google.com
はhttp://www.google.com
とhttps://www.google.com
の両方に一致します。 {placeholder_name}
形式のパスパラメータ プレースホルダは、1 つ以上の文字に一致します。たとえば、http://www.example.com/users/{id}
はhttp://www.example.com/users/4
に一致します。Navigation コンポーネントは、プレースホルダ名を、ディープリンク デスティネーション用に定義された引数とマッチングすることにより、プレースホルダ値を解析して適切な型に解決しようと試みます。同じ名前を持つ引数が定義されていない場合は、デフォルトのString
型が引数の値に使用されます。ワイルドカード「.*」を使用すると、0 個以上の文字に一致させることができます。- クエリ パラメータ プレースホルダは、パスパラメータの代わりに使用することも、パスパラメータと一緒に使用することもできます。たとえば、
http://www.example.com/users/{id}?myarg={myarg}
はhttp://www.example.com/users/4?myarg=28
に一致します。 - デフォルト値または null 許容値で定義された変数のクエリ パラメータ プレースホルダは、マッチングが不要です。たとえば、
http://www.example.com/users/{id}?arg1={arg1}&arg2={arg2}
はhttp://www.example.com/users/4?arg2=28
またはhttp://www.example.com/users/4?arg1=7
と一致します。この点がパスパラメータと異なります。たとえば、http://www.example.com/users?arg1=7&arg2=28
は、必須のパスパラメータが指定されていないため、上記のパターンに一致しません。 - 追加のクエリ パラメータは、ディープリンク URI のマッチングには影響しません。たとえば、
extraneousParam
が URI パターンで定義されていなくても、http://www.example.com/users/{id}
はhttp://www.example.com/users/4?extraneousParam=7
に一致します。
- スキーマのない URI は、http または https のいずれかと見なされます。たとえば、
(省略可)自分が URI のオーナーであることが必ず Google によって検証されるようにするには、[Auto Verify] チェックボックスをオンにします。詳しくは、Android アプリリンクを検証するをご覧ください。
[Add] をクリックします。選択したデスティネーションの上にリンクアイコン が表示され、そのデスティネーションがディープリンクを持つことが示されます。
[Code] タブをクリックして、XML ビューに切り替えます。ネストされた
<deepLink>
要素がデスティネーションに追加されています。<deepLink app:uri="https://www.google.com" />
暗黙的ディープリンクを有効にするには、アプリの manifest.xml
ファイルに要素を追加する必要もあります。既存のナビゲーション グラフをポイントするアクティビティに対して、単一の <nav-graph>
要素を追加します。次の例をご覧ください。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <application ... > <activity name=".MainActivity" ...> ... <nav-graph android:value="@navigation/nav_graph" /> ... </activity> </application> </manifest>
プロジェクトをビルドする際、Navigation コンポーネントは、<nav-graph>
要素を生成された <intent-filter>
要素に置き換えて、ナビゲーション グラフ内のすべてのディープリンクに一致するようにします。
暗黙的ディープリンクをトリガーする場合、暗黙的 Intent
を Intent.FLAG_ACTIVITY_NEW_TASK
フラグ付きで起動したかどうかによって、バックスタックの状態が変わります。
- フラグがセットされている場合、タスク バックスタックはクリアされ、ディープリンク デスティネーションに置き換えられます。明示的ディープリンクと同様、グラフをネストしている場合は、各ネストレベルの開始デスティネーション(つまり、階層内の各
<navigation>
要素の開始デスティネーション)もスタックに追加されます。そのため、ユーザーがディープリンク デスティネーションから [戻る] ボタンを押すと、アプリにそのエントリ ポイントからアクセスしたかのようにナビゲーション スタックを戻ることができます。 - フラグがセットされていない場合、ユーザーは、暗黙的ディープリンクをトリガーした元のアプリのタスクスタック上にとどまります。この場合、[戻る] ボタンを押すと前のアプリに戻り、[上へ] ボタンを押すと、ナビゲーション グラフ階層内の親デスティネーション上にあるアプリのタスクが開始されます。
ディープリンクの処理
Navigation を使用する際は、常にデフォルトの standard
launchMode
を使用することを強くおすすめします。standard
起動モードを使用すると、Navigation は Intent
内の明示的・暗黙的ディープリンクを処理する handleDeepLink()
を呼び出して、ディープリンクを自動的に処理します。しかし、singleTop
など別の launchMode
を使用すると、Activity
が再使用された際に自動的に処理されません。その場合は、次の例に示すように、onNewIntent()
で handleDeepLink()
を手動で呼び出す必要があります。
Kotlin
override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) navController.handleDeepLink(intent) }
Java
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); navController.handleDeepLink(intent); }
参考情報
ナビゲーションについて詳しくは、以下の参考情報をご確認ください。