WebViewでDeepLinkを使おうと思って苦戦した話

# 0. 要件

WebViewで特定のページを開いた場合、そのままWebViewで該当ページを開くのではなくアプリのページを開くようにしたい。

食べログさんなどがわかりやすいと思うので例に出させていただきますが、店舗の詳細ページを開こうとするとアプリに自動的に遷移するアレです。本要件を実現するとアプリ内を回遊出来るようになるのでユーザーの離脱を防ぐことが出来るようになるというメリットがあります。

アプリ開発に入門し、少しずつ慣れてきた頃だったので「おっアプリの特定ページに遷移ということはDeepLinkだ！」と思っていましたが苦戦した…という話になります。結論から先に書いてしまいますが、DeepLinkは使いませんでした。詳細書いていきます。

# 1. DeepLinkとは

Firebase Dynamic Links、Universal Links、Custom URL Scheme…と色々ありますが、それぞれ何が何なのかいまいち理解しきれていいなかったので改めて整理しました。

今回でいうところのDeepLinkとは、

> スマートフォンやタブレット端末のアプリケーションソフト（アプリ）で、外部のWebサイトや他のアプリなどから、アプリ内の特定のコンテンツや機能へリンクを張ること

を言います。

Ref: https://e-words.jp/w/ディープリンク.html

そのため、後述するFirebase Dynamic LinksやCustom URL Schemeなどは全てDeepLinkになります。

## Custom URL Scheme

アプリ間連携する際に必ずといっていいほど登場しますがGoogle Mapsでいうところの、`comgooglemaps://`といった形式の形のものです。

比較的古い技術にはなるそうですがまだまだ使われている技術で、いくつか採用デメリットがあります。

- アプリが端末にインストールされていない場合はエラーになってしまう
- 他のアプリと定義値が重複する可能性があり、意図した挙動にならない場合がある
- 「アプリを開きますか？」といった確認ダイアログが必ず表示されるのでUXが少なからず悪くなってしまう

Ref: 

- [https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app)
- [https://developer.android.com/training/app-links/deep-linking?hl=ja](https://developer.android.com/training/app-links/deep-linking?hl=ja)

## Universal Links

iOS 9以降で登場した技術です。先述のCustom URL Schemeのデメリットをカバーすることが出来ます。アプリがインストールされていない場合は別のWebページに遷移する、https形式なので独自ドメインを指定する、「アプリを開きますか？」といった確認ダイアログをスキップする、といったことが可能です。

Ref: [https://developer.apple.com/ios/universal-links/](https://developer.apple.com/ios/universal-links/)

ただしこちらの技術にもいくつかデメリットがあります。Universal Linksを適用するには`apple-app-site-association`というファイルをhttpsでホスティングされているWebサイトに配置する必要があり、「httpsでホスティングされているWebサイト」を用意する必要があります。また、`apple-app-site-association`ですが、iOS 14以降はApple管理下のCDNから取得されるそうで、配置先のサイトにIP制限をかけている場合などに少々厄介となります。

Ref: [https://dev.classmethod.jp/articles/ios-universal-link-developer-mode/](https://dev.classmethod.jp/articles/ios-universal-link-developer-mode/)

## App Links

AndroidでもUniversal Linksと似たような技術が用意されており、それがApp Linksです。メリット・デメリットはUniversal Linksと基本的に同じで、こちらの技術はAndroid6以降で利用可能です。Universal Linksと同じく設定ファイル（App Linksの場合は`assetlinks.json`）をhttpsでホスティングされているWebサイトに配置する必要があります。

[https://developer.android.com/training/app-links](https://developer.android.com/training/app-links)

## Firebase Dynamic Links

こちらはFirebaseが提供している技術になります。

Ref: [https://firebase.google.com/docs/dynamic-links?hl=ja](https://firebase.google.com/docs/dynamic-links?hl=ja)

アプリのインストールの有無にかかわらず、複数のプラットフォームで機能するリンクで、アプリのインストールが必要な場合には、アプリをインストール済みかどうかで挙動を変えることができます。例えば、アプリを未インストールの場合は特定のWEBサイトに遷移させたり、プラットフォームに合わせたアプリストアに遷移させたりといった挙動を定義することが出来ます。また、アプリストアに飛ばした場合、アプリをインストールした後もリンク情報が保持されているので、そのままアプリの特定ページに飛ばすことができます。

ここまでをみると、Universal LinksやApp Linksとの違いがそこまでないように見えますが、私が個人的に大きく違うなと感じる点は2点あります。

まず1点目が`apple-app-site-association`等の設定ファイルをホスティングする必要が無い点です。Firebaseがよろしく吸収してくれるので、検証中などで簡単にホスティングできるサイトがない場合にとても便利です。

次に、Firebase Dynamic LinksはGUIで簡単に扱えるという点です。Firebaseの管理コンソール上で定義することができます。ただし静的な値しか設定できず、ユーザーの操作によって値を動的にしたい場合などには使えません。動的に値を設定したい場合は、REST APIが用意されているのでそちらを使用する形になります。

Ref: https://firebase.google.com/docs/dynamic-links/rest?hl=ja

# 2. 調べた結果

ここまで調べて、Firebase Dynamic Links良いじゃん！と思いました。手軽に作成できる上に管理も楽だと考えたからです。

しかしながら、冒頭に述べた今回の要件を改めて整理していくとFirebase Dynamic LinksはおろかDeepLinkだめじゃん、、となりました。公式ドキュメントなどに情報が整理されていればよかったのですが、調べても全然出てこなく結局実際に実装してみて調べるということを行ったので余計に時間を使ってしまいました。。

# 3. なぜDeepLinkを使えなかったのか

まず今回の要件を改めて整理しますが、実現したいのは「WebViewから、ユーザーが任意のリンクを押下した際に、WebViewを閉じてアプリの特定ページに遷移する」ことです。

つまり、

1. WebViewから呼び出し可能であること
2. 動的にパラメータを付与できること
3. パラメータなどでアプリに情報譲渡可能であること

といったことが必要になります。

順番を逆に見ていきますが、3はどのDeepLinkでも可能です。言語にもよりますが、どのDeepLinkもURLと扱いは同じなので、クエリパラメータでもパスパラメータでも付与することができます。

2は、Firebase Dynamic Linksでは実現が簡単ではありません。REST APIを用いれば動的にリンクを作成することは可能なのですが、単純に工数が大きくなる上に、作成したリンクを確認できない（Firebaseコンソール上でも確認が出来ないですし、作成したリンクを取得するAPIも用意されていません）という問題があります。

最後に1ですが、どのDeepLinkでもWebViewから呼び出すことはできません。。WebViewから特定のユーザー操作を検知してネイティブのページに遷移させるには、URL変化を検知するフックという技術を使う必要があります。(これが明言されているサイトを見つけられなくてハマった。。)

# 4. 結論

DeepLinkについて綺麗にまとまっているサイトがなかったので、調べて理解するのにとても時間がかかってしまいました。。

実現可否を決める技術調査の場合、そもそもの要件は作業に取り掛かる前にしっかり整理しておきましょうという学びを得ました。