ブラウザやメールなどからURLをタップしたときに自分のアプリを開かせるには、IntentFilter でディープリンクを設定する。URLのパラメータをアプリ内に渡せる。
IntentFilter を設定する
AndroidManifest.xml の対象 Activity に IntentFilter を追加する。Android 12(API 31)以降は android:exported の明示的な設定が必須だ。外部アプリ(ブラウザやメールクライアント)からActivityを起動できるよう、true を設定する。
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="example.com"
android:pathPrefix="/items" />
</intent-filter>
</activity>
各要素の説明は以下のとおり。
| 要素 | 説明 |
|---|---|
action: VIEW | URLを表示するアクション。ディープリンクに必須 |
category: DEFAULT | 暗黙的インテントに対応するために必須 |
category: BROWSABLE | ブラウザからのリンクを受け取るために必須 |
data | マッチさせるURLのパターンを指定 |
pathPrefix="/items" の設定で https://example.com/items 以下のURLがアプリで開ける。
Activity でURLを受け取る
アプリが起動したら Intent から data を取得してURLを解析する。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
handleDeepLink(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
handleDeepLink(intent)
}
private fun handleDeepLink(intent: Intent) {
val uri = intent.data ?: return
// URLのパスを取得する
val path = uri.path
// URLのクエリパラメータを取得する
val itemId = uri.getQueryParameter("id")
}
}
intent.data はディープリンクで起動した場合のみ非nullになる。通常起動では null になるため ?: return でガードする。
launchMode が singleTop や singleTask の場合、アクティビティが起動済みだと onCreate() ではなく onNewIntent() が呼ばれる。両方でディープリンクを処理するために handleDeepLink() として共通化する。
URLパラメータを渡す
クエリパラメータを使うとURLからアプリへデータを渡せる。
https://example.com/items?id=42&category=books を受け取った場合:
val uri = intent.data ?: return
val itemId = uri.getQueryParameter("id") // "42"
val category = uri.getQueryParameter("category") // "books"
パスのセグメントからデータを取得するには pathSegments を使う。
https://example.com/items/42 の場合:
val uri = intent.data ?: return
// ["items", "42"] のリストが得られる
val segments = uri.pathSegments
val itemId = segments.getOrNull(1) // "42"
複数のURLパターンに対応する
複数の IntentFilter を設定すると、異なるURLパターンに対応できる。
<activity
android:name=".MainActivity"
android:exported="true">
<!-- https://example.com/items に対応 -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="example.com"
android:pathPrefix="/items" />
</intent-filter>
<!-- https://example.com/users に対応 -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="example.com"
android:pathPrefix="/users" />
</intent-filter>
</activity>
カスタムスキームを使う
https の代わりにアプリ独自のスキームも使える。
<data
android:scheme="myapp"
android:host="open"
android:pathPrefix="/items" />
scheme="myapp" の設定で myapp://open/items?id=42 でアプリを開ける。ただしカスタムスキームは他のアプリと衝突する可能性があるため、https スキームを使う方が安全だ。
https スキームでアプリを自動的に開く(App Links)
https スキームでディープリンクを設定しただけでは、URLをタップしたときにブラウザとアプリのどちらで開くかを選ぶダイアログが表示される。アプリが自動的に開くようにするにはAndroid App Linksの設定が必要だ。
android:autoVerify="true" を IntentFilter に追加する。
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="example.com"
android:pathPrefix="/items" />
</intent-filter>
さらに対象ドメインの https://example.com/.well-known/assetlinks.json にDigital Asset Linksファイルを配置し、ドメインとアプリの紐付けをOSが検証できるようにする。ファイルにはアプリのパッケージ名とSHA-256フィンガープリントを記述する。
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.myapp",
"sha256_cert_fingerprints": ["AA:BB:CC:..."]
}
}]
SHA-256フィンガープリントはリリース用キーストアから以下のコマンドで取得できる。
keytool -list -v -keystore release.jks -alias [key alias]
adb でディープリンクをテストする
adb shell am start \
-W -a android.intent.action.VIEW \
-d "https://example.com/items?id=42" \
com.example.myapp
com.example.myapp は自分のアプリのパッケージ名に置き換える。
