【Flutter】flutterでDeepLinkを実装する（URLでアプリを開く）

# Deep Linkとは

Deep Linkは、モバイルアプリケーション内の特定のコンテンツに直接リンクすることができるリンクです。たとえば、特定の製品ページ、チュートリアル、または検索結果に直接リンクすることができます。Deep Linkは、ユーザーがアプリを開いている場合にのみ機能します。

>ディープリンク（Deep link）、ディープリンキング（Deep linking）は、あるウェブページから他のウェブサイトのトップページ以外の各コンテンツ（ウェブページ・画像等）に直接ハイパーリンクを張ること。他サイトの画像などを自サイト内に直接参照（「表示」など）させること（→直リンク）とは異なり、単にリンクアンカーによりポインタを示すのみの行為を指す。

https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%AA%E3%83%B3%E3%82%AF

ここで実現したいのは**Deep Link**　経由で他のアプリまたはWebブラウザからFlutterアプリを開くことです。

# Dynamic Link
ここでは、詳細述べませんが、Deep Linkと同じような機能を持っているリンクタイプを挙げます。
**Dynamic Link** は、Firebase Dynamic Linksを使用して生成されるリンクであり、複数のプラットフォーム間で機能する単一のリンクです。これは、Webページ、iOSアプリ、Androidアプリの間で移動することができます。Dynamic Linkは、ユーザーがアプリをインストールしていない場合でも、正しいプラットフォームのアプリストアに自動的に誘導することができます。

**Dynamic Link** は、アプリがインストールされていない場合にも機能するため、アプリをダウンロードしてインストールするユーザーを増やすのに役立ちます。**Deep Link** は、アプリ内でのユーザーエンゲージメントを向上させるのに役立ちます。

# 使うパッケージ
https://pub.dev/packages/app_links

```yaml
dependencies:
      app_links: ^6.4.0
```

# 初期設定
## Android
android/app/src/main/AndroidManifest.xml

```xml
<activity ...>
    <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="schemeName"
            android:host="hostName" />
    </intent-filter>
</activity>

```

## iOS
ios/Runner/Info.plist
```php
<?xml ...>
<!-- ... other tags -->
<plist>
<dict>
  <!-- ... other tags -->
  <key>CFBundleURLTypes</key>
  <array>
    <dict>
      <key>CFBundleTypeRole</key>
      <string>Editor</string>
      <key>CFBundleURLName</key>
      <string>[ANY_URL_NAME]</string>
      <key>CFBundleURLSchemes</key>
      <array>
        <string>[YOUR_SCHEME]</string>
      </array>
    </dict>
  </array>
  <!-- ... other tags -->
</dict>
</plist>

```

上記の設定でdeep Linkは「`shcemeName://hostName`」となり、それを呼び出すことで、アプリを開くことができます。

呼び出しにパラメーターを追加したい場合、末尾に`?parameter=para`をつけます。


# エミュレータにて動作確認

## iOS
```sh
xcrun simctl openurl booted "schemeName://hostName/?parameter=para"  
```
`xcrun simctl openurl`コマンドでDeep Linkを開く際に、クエリパラメーターを含める場合、URLエンコードが必要です。つまり、?や=などの特殊文字をエンコードする必要があります。
従って、エンコードされたURLを使用することをお勧めします。
上記のコマンドの`"schemeName://hostName/?parameter=para" `の二重引用符は忘れないように！

## Android
```sh
adb -e shell 'am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "schemeName://hostName/?parameter=para"'
```
実機確認する場合は`adb -e`を`adb -d`に変えれば呼び出せます。

# パラメーターの取得
Deep Linkで呼び出された場合、下記のソースでリンクURLやパラメーターを取得できます。

```dart
import 'package:app_links/app_links.dart';

StreamSubscription _sub;

  Future<void> initUniLinks(BuildContext context) async {
    final appLinks = AppLinks();
    _sub = appLinks.uriLinkStream.listen(
      (Uri? uri) async {
        if (uri != null) {
          //さっき設定したスキームをキャッチしてここが走る。
          String? authCode = uri.queryParameters['code'];
          if (authCode != null) {
            WidgetsBinding.instance.addPostFrameCallback((_) {
              authVerifySAML(authCode, context);
            });
          }
        }
      },
      onError: (err) {
        logger.e(err);
      },
    );
  }

```

結果：
~~~
flutter: para
~~~