バージョン 1.2.0 以降、Navigation 3 では、
DeepLinkRequest クラスと
DeepLinkMatcher クラスを使用して、アプリ内のデスティネーションへのディープリンクがサポートされています。
アプリでディープリンクをサポートするには、次の手順を完了します。
- アプリが処理できる URI を指定するには、
AndroidManifest.xmlでインテント フィルタを定義 します。 - 受信リクエストを
ナビゲーション キーにマッピングする
DeepLinkMatcherインスタンスを作成 します。 - アクティビティの
onCreateメソッドまたはonNewIntentメソッドで受信リクエストを照合 し、それに応じてバックスタックを更新します。
DeepLinkRequest を作成する
DeepLinkRequest は、受信ディープリンクを表します。これには、
DeepLinkUri と、インテントのアクションや MIME タイプなどの追加
情報を含むオプションの RequestExtras が含まれます。
// Create a request with a String URI val request = DeepLinkRequest(uri = "https://www.example.com/home") // Create a request from a DeepLinkUri val deepLinkUri = DeepLinkUri("https://www.example.com/home") val requestFromUri = DeepLinkRequest(uri = deepLinkUri) // Create a request with a URI and action val requestWithAction = DeepLinkRequest( uri = "https://www.example.com/home", extras = DeepLinkRequest.actionExtra("android.intent.action.VIEW") ) // Create a request with URI, action and mimeType val requestWithMimeType = DeepLinkRequest( uri = "https://www.example.com/image", extras = requestExtras { put(DeepLinkRequest.ActionExtrasKey, "android.intent.action.VIEW") put(DeepLinkRequest.Companion.MimeTypeExtrasKey, "image/png") } )
DeepLinkRequest のエクストラを提供する
ディープリンクに関連する追加情報を保存するには、
RequestExtras クラスを使用します。エクストラを型安全に定義してインスタンス化するために、
ライブラリには RequestExtrasKey インターフェースと
requestExtras DSL が用意されています。
また、ライブラリには 2 つのエクストラキーと関連するヘルパーが用意されています。
MimeTypeExtrasKey: MIME タイプStringの保存に使用します。ActionExtrasKey(Android のみ):IntentのアクションStringの保存に使用します。
val extras: RequestExtras = requestExtras { put(DeepLinkRequest.Companion.MimeTypeExtrasKey, "application/json") put(DeepLinkRequest.ActionExtrasKey, Intent.ACTION_VIEW) } // Access typed values using the get operator val mimeType: String? = extras[DeepLinkRequest.Companion.MimeTypeExtrasKey] val action: String? = extras[DeepLinkRequest.ActionExtrasKey] // Create extras using helper functions and combine them val mimeTypeExtras: RequestExtras = DeepLinkRequest.mimeTypeExtra("application/json") val combinedExtras: RequestExtras = extras + DeepLinkRequest.actionExtra(Intent.ACTION_VIEW)
独自のカスタム エクストラを定義するには、型付きの汎用を使用して RequestExtrasKey
インターフェースを実装します。
// Define a custom typed key: object CampaignIdExtrasKey : RequestExtrasKey<String> val customExtras: RequestExtras = requestExtras { put(CampaignIdExtrasKey, "123") } val campaignId: String? = customExtras[CampaignIdExtrasKey]
emptyRequestExtras() を使用して空のインスタンスを作成したり、
+(plus)演算子と -(minus)演算子を使用してエクストラを組み合わせたりすることもできます。
Intent から DeepLinkRequest を作成する
Android では、Intent から直接 DeepLinkRequest を作成できます。この方法で作成された DeepLinkRequest は、次のように構築されます。
uriは、インテントのdataフィールドからコピーされます。- null でない場合、MIME タイプとアクションの エクストラは、 対応するインテント フィールドから設定されます。
- null 以外の値を持つ
intent.extrasはすべて、DeepLinkRequest.IntentExtrasKeyにSavedStateとして保存されます。 extrasパラメータを使用して指定された追加のエクストラが追加されます。
object CampaignIdExtrasKey : RequestExtrasKey<String> val intent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("https://www.example.com/item/42") type = "application/json" putExtra("user_id", "123") } val request = DeepLinkRequest( intent = intent, extras = requestExtras { put(CampaignIdExtrasKey, "spring_promo") } ) // The resulting DeepLinkRequest contains: val uri = request.uri // "https://www.example.com/item/42" val action = request.extras[DeepLinkRequest.ActionExtrasKey] // "android.intent.action.VIEW" val mimeType = request.extras[DeepLinkRequest.Companion.MimeTypeExtrasKey] // "application/json" val intentExtras: SavedState? = request.extras[DeepLinkRequest.IntentExtrasKey] val userId: String? = intentExtras?.read { getStringOrNull("user_id") } // "123" val campaignId: String? = request.extras[CampaignIdExtrasKey] // "spring_promo"
DeepLinkMatcher インスタンスを作成する
A DeepLinkMatcher は、受信した DeepLinkRequest インスタンスを
アプリのバックスタックに追加できるナビゲーション キーにマッピングします。Navigation 3
には、UriDeepLinkMatcher、StaticKeyDeepLinkMatcher、
BackStackMatcher の 3 つの組み込みマッチャーが用意されています。また、組み込み
マッチャーでカバーされていないユースケースで使用するカスタム マッチャーもサポートしています。
詳細については、DeepLinkMatcher を作成するをご覧ください。
インテント フィルタを追加する
ディープリンクでアクティビティを開始できるようにするには、アプリの AndroidManifest.xml で一致する
<intent-filter> 要素を定義する必要があります。詳細については、受信リンク用のインテント フィルタを追加するをご覧ください。
受信リクエストを照合する
`DeepLinkMatcher` インスタンスを作成DeepLinkMatcherしたら、アクティビティで受信リクエストを照合できます。
受信リクエストを照合するには、次の手順を完了します。
DeepLinkMatcherインスタンスをインスタンス化 します。- 明示的に、または
マルチバインディングを使用して、すべての
DeepLinkMatcherインスタンスを**照合**します。 - 受信した
IntentからDeepLinkRequestを作成 します。 - すべてのマッチャーに対してリクエストを照合 し、最適な一致を見つけます。
- 照合結果からバックスタックを作成 します。
// 1. Instantiate your DeepLinkMatcher instances. val homeMatcher = StaticKeyDeepLinkMatcher(HomeKey, listOf(DeepLinkMatcher.actionFilter(Intent.ACTION_VIEW))) val userProfileMatcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/users/{id}"), serializer<UserProfileKey>() ).withBackStack { matchResult -> listOf(HomeKey, matchResult.key) } val telMatcher = TelDeepLinkMatcher() // 2. Collate all of your DeepLinkMatcher instances. // Note: Collating matchers with different generic types requires wildcards, // erasing the specific generic types. val deepLinkMatchers: List<DeepLinkMatcher<*, *>> = listOf( homeMatcher, userProfileMatcher, telMatcher ) class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... // 3. Create a DeepLinkRequest from the incoming Intent val request = DeepLinkRequest(intent = intent) // 4. Match the request against all matchers and find the best match. // Because DeepLinkMatcher.MatchResult implements Comparable, you can // use maxOrNull() to find the best match. val matchResult = deepLinkMatchers .mapNotNull { it.match(request) } // List<DeepLinkMatcher.MatchResult<*>> .maxOrNull() // DeepLinkMatcher.MatchResult<*>? // 5. Create the back stack from the match result (or fall back to a default). val backStack: List<NavKey> = when (matchResult) { // If no match is found, use the default back stack (e.g., HomeKey) null -> listOf(HomeKey) // If a BackStackMatchResult is found, use the back stack from the result is BackStackMatchResult<*, *> -> { // Because star-projected matchers erase the key type, cast the back stack to List<NavKey>. @Suppress("UNCHECKED_CAST") matchResult.backStack as List<NavKey> } // Otherwise, use the key from the match result to make a single-item back stack else -> listOf(matchResult.key as NavKey) } } }