すべての記事
mobiledeep linksiOSAndroid

localhost トンネルでモバイルディープリンクをテスト

iOS の Universal Links と Android の App Links は、どちらもドメインのルートに HTTPS で配信される JSON ファイルを要求します。iOS は /.well-known/apple-app-site-association。Android は /.well-known/assetlinks.json。localhost は、OS がアプリに関連づけるホスト名でどちらも配信できません。だからトンネルします。

各プラットフォームの実際の要件

iOS Universal Links

アプリのインストール時に OS が https://your-domain.com/.well-known/apple-app-site-association(または /apple-app-site-association)を取得します。アプリの associated domains エンタイトルメントと内容を照合します。取得は本物の HTTPS で成功する必要があります。iOS はこの目的で自己署名証明書を信頼せず、localhost も信頼しません。

Android App Links

Android は https://your-domain.com/.well-known/assetlinks.json を取得して App Links を検証します。ファイルにはアプリの SHA-256 フィンガープリントを列挙する必要があります。検証はインストール時と初回起動時に行われます。同じ制約:本物の HTTPS、本物のドメイン。

なぜ localhost では直接できないのか

mkcert がノート PC のブラウザーで信頼された HTTPS を与えても、モバイル OS はあなたのローカル CA を信頼しません。そして apple-app-site-association のドメインは、アプリのエンタイトルメントの associated-domain と一致する必要があり——それは localhost ではなく、DNS で解決可能な本物のドメインです。

専用の staging ドメインで回避するチームもあります。動きますが、反復ループが遅い。localhost トンネルは、モバイルデバイスが文句なく到達する本物のサブドメイン上の本物の HTTPS URL を与えます。

配線の仕方

  1. ローカル dev サーバーの /.well-known/ から apple-app-site-associationassetlinks.json を配信。両ファイル。両ルート。
  2. npx portpreview 3000(dev サーバーの使うポート)を実行。
  3. トンネルのホスト名をメモ——abc123.portpreview.dev のような。
  4. iOS アプリの associated domains エンタイトルメントに applinks:abc123.portpreview.dev を追加。Android の intent filter に同じホストを。
  5. 実機でアプリをビルド・インストール(シミュレーターは Universal Link の挙動が変)。
  6. 別のアプリ——メモ、メール、QR コード——から URL を開き、ブラウザーではなくインストール済みアプリにルートされるのを見る。

ディープリンクのトンネリングの落とし穴:予約サブドメインがない限り、トンネルのホスト名はセッション間で変わります。ローテーションごとに、新しい associated-domain エントリでアプリを再ビルドする必要があります。ディープリンクの挙動を頻繁に反復するなら、予約サブドメインを取得しましょう。

apple-app-site-association では content-type が重要

iOS は拡張子なしのファイルと、content-type application/json(新しい iOS)または application/pkcs7-mime(古い、署名形式)を期待します。ほぼすべての現代アプリはプレーン JSON バリアントを使います。dev サーバーが正しい content-type を返すことを確認してください。さもないと iOS は有用なエラーもなく静かにファイルを拒否します。

まずデスクトップブラウザーからテスト:https://your-tunnel.portpreview.dev/.well-known/apple-app-site-association を開き、JSON がレンダリングされ、dev tools の content-type ヘッダーが正しいことを確認。間違っていれば、シミュレーターで Universal Link バグを追う前に直しましょう。

その他のディープリンクデバッグの罠

アプリエンタイトルメントの不一致

associated-domains エンタイトルメントが applinks:abc.portpreview.dev なのに apple-app-site-association が def.portpreview.dev を列挙していると、iOS は取得しません。ホスト名は一貫させる必要があります。

Safari 内からの Universal Link

Safari 内(タブのある同じアプリ)で Universal Link をタップすると、アプリではなく Safari で開くことがあります。これは仕様です——iOS は「ユーザーがリンクをクリックするたびにアプリを開く」というトリックを防ぎます。代わりにメモやメールからテストしてください。

Android App Links と digital asset links

Android は カスタム URL スキームyourapp://path)もサポートし、HTTPS や assetlinks.json は不要です。テストは簡単ですが安全性は低い——どのアプリも同じスキームを登録できます。本番品質のディープリンクなら、App Links が答えです。

私たちが使うモバイルテストフロー

ディープリンクつきで iOS と Android の両方を出荷するプロジェクトでは:

  1. .well-known ファイルを配信するバックエンドを起動。
  2. npx portpreview 3000 でトンネル。
  3. トンネル URL がセッションで安定したら(または予約サブドメインを使う)、アプリの associated-domain エントリを更新してビルド。
  4. 実機で QA——新規インストールと更新の両方。
  5. OAuth とディープリンクの組み合わせ(アプリに戻ってリダイレクトするサインインプロバイダー)は OAuth コールバックテストと組み合わせる。

セットアップは初回は面倒です。その後、トンネル URL は Xcode と Gradle スキームのもう 1 つの env 変数にすぎません。

より広いモバイルテストパターンは localhost トンネルでのモバイルテストを参照。PortPreview のウェイトリストへ。

よくある質問

iOS Universal Links を localhost でテストできますか?
直接はできません。Universal Links は、iOS が本物のドメインから本物の HTTPS で apple-app-site-association を取得することを要求します。localhost は資格がありません。トンネルは、associated-domains エンタイトルメントに記載すれば iOS がアプリに関連づけるトンネルサブドメイン上の HTTPS URL を与えます。
apple-app-site-association はどの content-type を使うべき?
現代の iOS は application/json を期待します。古いバージョンは署名ファイル向けに application/pkcs7-mime も受け入れました。今日のほとんどのアプリはプレーン JSON バリアントを使います。iOS がファイルを拾わないなら、まずデスクトップブラウザーから content-type ヘッダーを確認してください。
Android App Links はローカルテストにトンネルが必要ですか?
完全な App Link 検証(カスタム URL スキームでなく)を望むならはい。Android は intent filter のドメインから本物の HTTPS で assetlinks.json を取得します。トンネルは、デバイスが検証できるドメイン上の本物の HTTPS URL を提供します。カスタムスキームはこれを必要としませんが安全性は低いです。