Upgrade to Pro — share decks privately, control downloads, hide ads and more …

多数のアプリを支えるAndroid App Links運用 〜Manifest動的変更で運用を...

多数のアプリを支えるAndroid App Links運用 〜Manifest動的変更で運用を楽にする話〜 / Managing Android App Links Across Many Apps: Easing Operations with Dynamic Manifest Updates

「YapTech Playground #1 モバイルアプリ開発編」登壇資料
https://yappli.connpass.com/event/359014/

「URLを起点に、外部からアプリの特定画面へユーザーをより安全かつシームレスに誘導したい」。この課題を解決するのがAndroid App Linksです。

本発表では、まずApp Linksの概要とヤプリでの開発方法を簡単にご紹介します。 さらに、多数のアプリを扱うヤプリだからこそ、App Linksをオプション機能として提供する中で直面した、ある厄介な課題に注目。この運用上の悩みを、ビルドフローに仕込んだ「Android App Linksの情報を動的に変更させる方法」でどのように解決したのか。その具体的なアプローチをコードを交えてご紹介します。

App Linksの導入を検討している方や、いざ実装する時に役立つかもしれないヒントとしていただければと思います。

Avatar for Yappli Developers

Yappli Developers

July 27, 2025
Tweet

More Decks by Yappli Developers

Other Decks in Technology

Transcript

  1. INDEX ⽬次 1. Android AppLinksとは 2. 実装時に直⾯した課題 a. Applinksを使⽤しないアプリには情報を記載しない b.

    アプリによってManifestに記載する情報を切り替える 3. 解決アプローチ 4. さいごに
  2. 2つの大きな特徴 1. Android AppLinksとは ⾼いセキュリティ 従来のリンク Android AppLinks シームレス URLをタップすると

    「どのアプリで開きますか?」という 選択画⾯が表⽰され、⼀⼿間かかる 選択画⾯を完全にスキップし URLから直接アプリが起動する 第三者による「なりすまし」や 「リンクの乗っ取り」が可能 アプリとWebサイトが 「公式な関係である」ことを 検証‧承認しているので安全 公式ページ:https://developer.android.com/training/app-links?hl=ja
  3. 2. 実装時に直⾯した課題 Yappliのビルドフロー A社 B社 C社 manage (データ管理) サーバ A機能を使⽤

    B機能は不使⽤ ストア情報 etc… Android ソースコード ビルド Aアプリ Bアプリ Cアプリ
  4. 2. 実装時に直⾯した課題 Yappliのビルドフロー A社 B社 C社 manage (データ管理) サーバ A機能を使⽤

    B機能は不使⽤ ストア情報 etc… Aアプリ Bアプリ Cアプリ Android ソースコード ビルド
  5. 2. 実装時に直⾯した課題 1 <activity 2 android:name=".HogeHogeActivity" 3 android:exported="true"> 4 5

    <intent-filter android:autoVerify="true"> 6 <action android:name="android.intent.action.VIEW" /> 7 8 <category android:name="android.intent.category.DEFAULT" /> 9 <category android:name="android.intent.category.BROWSABLE" /> 10 11 <data android:scheme="https" /> 12 <data android:pathPrefix=".*" /> 13 <data android:host="yappli.applinks.host" /> 14 15 </intent-filter> 16 </activity>
  6. 2. 実装時に直⾯した課題 1 <activity 2 android:name=".HogeHogeActivity" 3 android:exported="true"> 4 5

    <intent-filter android:autoVerify="true"> 6 <action android:name="android.intent.action.VIEW" /> 7 8 <category android:name="android.intent.category.DEFAULT" /> 9 <category android:name="android.intent.category.BROWSABLE" /> 10 11 <data android:scheme="https" /> 12 <data android:pathPrefix=".*" /> 13 <data android:host="yappli.applinks.host" /> 14 15 </intent-filter> 16 </activity> このhostをアプリ毎に変えたい
  7. 3. 解決アプローチ Yappliのビルドフロー A社 B社 C社 Aアプリ Bアプリ Cアプリ ここで

    書き換える manage (データ管理) サーバ A機能を使⽤ B機能は不使⽤ ストア情報 etc… Android ソースコード ビルド
  8. 3. 解決アプローチ # applinksのhostが設定されている場合のみ処理を行う if jq -e '.applinks.host | select(.

    != null and . != "")' "apps/$appId/app-params.json"; then # --- この中にAndroidManifest.xmlを編集する処理が続く --- # (処理の詳細は次のスライドで) fi
  9. 3. 解決アプローチ # applinksのhostが設定されている場合のみ処理を行う if jq -e '.applinks.host | select(.

    != null and . != "")' "apps/$appId/app-params.json"; then # --- この中にAndroidManifest.xmlを編集する処理が続く --- # (処理の詳細は次のスライドで ) fi AppLinks不使⽤アプリのManifestにAppLinks情報を記載すると Google Play Consoleで警告⽂が表⽰される
  10. 3. 解決アプローチ # applinksのhostが設定されている場合のみ処理を行う if jq -e '.applinks.host | select(.

    != null and . != "")' "apps/$appId/app-params.json"; then # --- この中にAndroidManifest.xmlを編集する処理が続く --- # (処理の詳細は次のスライドで ) fi AppLinks不使⽤アプリのManifestにAppLinks情報を記載すると Google Play Consoleで警告⽂が表⽰される
  11. # 1. app-params.jsonからapplinksの値取得 applinks_data=$(jq -r '.applinks.host' "apps/$appId/app-params.json") # 2. 取得した値を元に<data>タグを動的に生成

    generated_tags_string=$( echo "$applinks_data" | tr ',' '\n' | while IFS= read -r host ...; do ... generated_tag=" <data android:host=\"$trimmed_host\" />" echo "$generated_tag" done ) # 3. 生成したタグを含んだintent-filterを作成 intent_filter_string=$(cat << EOF <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:pathPattern=".*" android:scheme="https" /> ${generated_tags_string} </intent-filter> EOF) 3. 解決アプローチ
  12. # 1. app-params.jsonからapplinksの値取得 applinks_data=$(jq -r '.applinks.host' "apps/$appId/app-params.json") # 2. 取得した値を元に<data>タグを動的に生成

    generated_tags_string=$( echo "$applinks_data" | tr ',' '\n' | while IFS= read -r host ...; do ... generated_tag=" <data android:host=\"$trimmed_host\" />" echo "$generated_tag" done ) # 3. 生成したタグを含んだintent-filterを作成 intent_filter_string=$(cat << EOF <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:pathPattern=".*" android:scheme="https" /> ${generated_tags_string} </intent-filter> EOF) 3. 解決アプローチ app-params.jsonからapplinksの値取得 例:aaa.applink, bbb.applink, ccc.applink
  13. # 1. app-params.jsonからapplinksの値取得 applinks_data=$(jq -r '.applinks.host' "apps/$appId/app-params.json") # 2. 取得した値を元に<data>タグを動的に生成

    generated_tags_string=$( echo "$applinks_data" | tr ',' '\n' | while IFS= read -r host ...; do ... generated_tag=" <data android:host=\"$trimmed_host\" />" echo "$generated_tag" done ) # 3. 生成したタグを含んだintent-filterを作成 intent_filter_string=$(cat << EOF <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:pathPattern=".*" android:scheme="https" /> ${generated_tags_string} </intent-filter> EOF) 3. 解決アプローチ 取得した値の数だけdataタグを⽣成
  14. # 1. app-params.jsonからapplinksの値取得 applinks_data=$(jq -r '.applinks.host' "apps/$appId/app-params.json") # 2. 取得した値を元に<data>タグを動的に生成

    generated_tags_string=$( echo "$applinks_data" | tr ',' '\n' | while IFS= read -r host ...; do ... generated_tag=" <data android:host=\"$trimmed_host\" />" echo "$generated_tag" done ) # 3. 生成したタグを含んだintent-filterを作成 intent_filter_string=$(cat << EOF <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:pathPattern=".*" android:scheme="https" /> ${generated_tags_string} </intent-filter> EOF) 3. 解決アプローチ intent-filterに 作ったdataタグを埋め込む
  15. 3. 解決アプローチ Yappliのビルドフロー A社 B社 C社 Aアプリ Bアプリ Cアプリ ここで

    書き換える manage (データ管理) サーバ A機能を使⽤ B機能は不使⽤ ストア情報 etc… Android ソースコード ビルド
  16. # 1. app-params.jsonからapplinksの値取得 applinks_data=$(jq -r '.applinks.host' "apps/$appId/app-params.json") # 2. 取得した値を元に<data>タグを動的に生成

    generated_tags_string=$( echo "$applinks_data" | tr ',' '\n' | while IFS= read -r host ...; do ... generated_tag=" <data android:host=\"$trimmed_host\" />" echo "$generated_tag" done ) # 3. 生成したタグを含んだintent-filterを作成 intent_filter_string=$(cat << EOF <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:pathPattern=".*" android:scheme="https" /> ${generated_tags_string} </intent-filter> EOF) 3. 解決アプローチ アプリ毎にManifestに記載する情報が異なる
  17. # 1. app-params.jsonからapplinksの値取得 applinks_data=$(jq -r '.applinks.host' "apps/$appId/app-params.json") # 2. 取得した値を元に<data>タグを動的に生成

    generated_tags_string=$( echo "$applinks_data" | tr ',' '\n' | while IFS= read -r host ...; do ... generated_tag=" <data android:host=\"$trimmed_host\" />" echo "$generated_tag" done ) # 3. 生成したタグを含んだintent-filterを作成 intent_filter_string=$(cat << EOF <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:pathPattern=".*" android:scheme="https" /> ${generated_tags_string} </intent-filter> EOF) 3. 解決アプローチ アプリ毎にManifestに記載する情報が異なる
  18. 4. さいごに 1. Android AppLinksとは 2. 実装時に直⾯した課題 a. Applinksを使⽤しないアプリには情報を記載しない b.

    アプリによってManifestに記載する情報を切り替える 3. 解決アプローチ a. アプリビルド時にシェルスクリプトを実⾏しManifestにintent-filterを追記する