Flutterでディープリンクを修正する機会があったので、設定・実装の全体像をまとめてみました。
ディープリンクとは
WebサイトのURLから、直接アプリのコンテンツを開くことができる技術のことです。
iOSではUniversal Links(ユニバーサルリンク)と呼ばれ、Androidではアプリリンクと呼ばれています。
(技術的な仕様は少し違いますがここでは省きます)
X(旧Twitter)やInstagramなどのURLをタップしたときに、アプリをインストールしていれば、ブラウザではなくアプリでそのコンテンツが表示されるものです。
アプリ側の設定方法
iOS
まずはApple Developper Programのサイトの「Certificates, Identifiers & Profiles」のページを開き、「Associated Domains」をONにします。

次にXcodeの「Runner」→「Signing & Capabilities」→「Associated Domains」に後述するapple-app-site-associationを保存するドメインを指定します。

Android
android/app/src/main/AndroidManifest.xmlに以下を追加します。
<!-- App Links -->
<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" />
    <!-- Accepts URIs that begin with https://YOUR_HOST -->
    <data
      android:scheme="https"
      android:host="[YOUR_HOST]" />
</intent-filter>
apple-app-site-associationの設定方法
iOSではアプリとWebサイトを紐づけるために、apple-app-site-associationというファイルを用意し、サーバーにアップロードします。
実際のファイルは以下のように書きます。
{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "ABCDFE.com.example.app",
                "paths": ["*"]
            }
        ]
    }
}
「appID」はdevelopperチームのIDに、アプリのバンドルIDを繋げたものです。
また「paths」にはWebサイトのパスを指定できます。今回は全てのパスを渡せるワイルドカードを使っています。
そして以下の場所でファイルにアクセスできるようにアップロードします。
https://{domain}/.well-known/apple-app-site-association
assetlinks.jsonの設定方法
AndroidでもアプリとWebサイトを紐づけるために、assetlinks.jsonというファイルを用意し、サーバーにアップロードします。
記載内容は以下のとおりです。
 [{
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example",
      "sha256_cert_fingerprints":
      ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
    }
  }]
そして以下の場所でファイルにアクセスできるようにアップロードします。
https://{domain}/.well-known/assetlinks.json
実装方法
↓↓「Uni Links」というプラグインを使います。
https://pub.dev/packages/uni_links
まずはアプリが開始された時のUriオブジェクトを返す処理を行います。
この処理はアプリ開始の初期に一度だけ実行します。
import 'dart:async';
import 'package:uni_links/uni_links.dart';
import 'package:flutter/services.dart';
Future _initURIHandler() async {
    try {
      final initialURI = await getInitialUri();
    } on PlatformException {
      debugPrint("Failed to receive initial uri");
    }
 }
次にディープリンクを認識したときの処理を書きます。
ここでは、 ディープリンクを認識したらpushDeepLink()が呼ばれ、そのメソッド内で画面遷移が実行されます。
StreamSubscription _sub;
Future initUniLinks() async {
    _sub = linkStream.listen((String? link) {
      pushDeepLink();
    }, onError: (err) {
      debugPrint('Error occurred: $err');
    });
}
Future pushDeepLink() async {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) {
          return TestPage();
        },
      )
    );
 }
まとめ
本記事のまとめは以下のとおりです。
- iOSは「Associated Domains」の設定を行い、apple-app-site-associationを作成しサーバーにアップロードする。
 - AndroidはAndroidManifest.xmlにタグを追加し、assetlinks.jsonを作成しサーバーにアップロードする。
 - 「Uni Links」というプラグインを使い、公式通りに実装する。
 
最後までお読みいただきありがとうございました。
参考文献
https://pub.dev/packages/uni_links
https://developer.apple.com/documentation/xcode/supporting-associated-domains
https://developer.android.com/training/app-links/verify-android-applinks?hl=ja