maui-deep-linking について
.NET MAUI で Android と iOS のディープリンクを実装・デバッグするためのスキルです。プラットフォームごとのライフサイクル、リンク検証、Shell ルーティング、設定上のよくある問題を扱います。
主な機能
- 01Android のコールド/ウォームスタートに対応
- 02検証済み Android App Links の設定
- 03iOS Universal Link の各起動経路を解説
- 04ドメイン関連ファイルと署名鍵の確認
- 05メインスレッドでの Shell ナビゲーション
- 06プラットフォーム別デバッグ項目
活用シーン
- 01Android リンクで選択画面が出る問題の診断
- 02実機 iOS での Universal Links のデバッグ
- 03アプリ状態ごとのリンク失敗の防止
- 04Shell ルートとドメイン関連設定の検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ davidortinau/ maui-skills --skill maui-deep-linkingインストール後、Claude Code で/maui-deep-linkingを入力して読み込まれたか確認します。
同梱ファイルreferences/deep-linking-api.md
詳細
.NET MAUI のディープリンク
プラットフォーム固有の注意点
Android
- App Links では
IntentFilterにAutoVerify = trueが必要です(ディープリンクだけの場合とは異なります)。これがないと、Android はアプリを直接開かず、アプリを選択するダイアログを表示します。 OnCreateとOnNewIntentの両方でインテントを処理します。OnCreateはコールドスタート時に呼び出され、OnNewIntentはアプリの実行中に呼び出されます。どちらか一方でも欠けていると、特定の状況でリンクが何も表示されずに失敗します。
// ❌ Only handles cold-start links
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
HandleDeepLink(Intent);
}
// ✅ Handles both cold-start and warm-start links
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
HandleDeepLink(Intent);
}
protected override void OnNewIntent(Intent? intent)
{
base.OnNewIntent(intent);
HandleDeepLink(intent);
}
- **SHA-256 フィンガープリントは、テスト対象のビルドに使用した署名キーと一致している必要があります。**デバッグビルドとリリースビルドでは異なるキーが使用されるため、それに応じて
assetlinks.jsonを更新しないと、検証が何も表示されずに失敗します。 - 次のコマンドで検証ステータスを確認します:
adb shell pm get-app-links com.example.myappaskだけでなく、verifiedステータスが表示されることを確認してください。
iOS
- ⚠️ **ユニバーサルリンクはシミュレーターでは動作しません。**実機でテストする必要があります。
- AASA の変更が Apple の CDN に反映されるまで、最大 24 時間かかります(iOS 14 以降)。開発中は、
?mode=developerクエリパラメーターまたは Apple の CDN 診断コマンドswcutil dl -d example.comを使用してください。 - 次の 3 つのエントリーポイントすべてを処理します:
FinishedLaunching、ContinueUserActivity、SceneWillConnect。いずれかが欠けていると、特定のアプリ状態(コールドスタート、バックグラウンドからの再開、シーンベースの起動)でリンクが失敗します。 - Associated Domains エンタイトルメントには
applinks:プレフィックスが必要です。applinks:example.comではなくexample.comだけを指定すると、何も表示されずに失敗します。
よくある間違い
MainThread.BeginInvokeOnMainThread の指定忘れ
ディープリンクのコールバックはバックグラウンドスレッドで実行される場合があります。Shell のナビゲーションはメインスレッドで実行する必要があります。
// ❌ May crash — GoToAsync called off the main thread
static void HandleUniversalLink(string? url)
{
if (string.IsNullOrEmpty(url)) return;
Shell.Current.GoToAsync(MapToRoute(url));
}
// ✅ Dispatch to main thread
static void HandleUniversalLink(string? url)
{
if (string.IsNullOrEmpty(url)) return;
MainThread.BeginInvokeOnMainThread(async () =>
await Shell.Current.GoToAsync(MapToRoute(url)));
}
ナビゲーション前にルートが登録されていない
ディープリンクが実行される前に、AppShell コンストラクターで Shell のルートを登録してください。ルートが存在しない場合、GoToAsync は例外を表示せずに発生させるか、ルートに移動します。
カスタム URI スキームと App Links/ユニバーサルリンク
| 方法 | 検証済み | ブラウザーへのフォールバック | 推奨 |
|---|---|---|---|
カスタム URI スキーム(myapp://) | いいえ | いいえ | アプリ間通信に限る |
Android App Links(https://) | はい | はい | ✅ 本番環境のウェブリンク |
iOS ユニバーサルリンク(https://) | はい | はい | ✅ 本番環境のウェブリンク |
⚠️ カスタム URI スキームは検証されません。同じスキームをどのアプリでも登録できます。ユーザー向け URL には
https://の App Links/ユニバーサルリンクを使用してください。
デバッグ用チェックリスト
- Android:
MainActivityのIntentFilterにAutoVerify = trueが設定されている - Android:
/.well-known/に、現在の署名キーに対応する正しい SHA-256 を含むassetlinks.jsonがある - Android:インテントが
OnCreateとOnNewIntentの両方で処理されている - Android:
adb shell pm get-app-linksで検証済み - iOS:Associated Domains エンタイトルメントに
applinks:example.comがある(example.comだけではない) - iOS:正しい Team ID を含む AASA ファイルが
/.well-known/apple-app-site-associationにある - iOS:ライフサイクルの 3 つのエントリーポイントすべてが処理されている
- iOS:実機でテスト済み(シミュレーターではない)
- ディープリンクのコールバックが実行される前に Shell のルートが登録されている
- ナビゲーションがメインスレッドにディスパッチされている
コメント
Markdown 対応