FirebaseDynamicLinksを実装する~iOS版~


概要

最近FirebaseDynamicLinksを導入する機会があったのですが、FirebaseDynamicLinksの導入は頻繁に行う作業ではないので、いざ導入しようとすると手順を忘れがちです。そこで備忘録として、FirebaseDynamicLinksの導入手順とついでに関連用語の説明を残しておこうと思います。

まずは関連用語の説明から

ディープリンク

ディープリンクとは、Webサイトなどにあるリンクからアプリの特定の画面に遷移させることができるリンクです。ディープリンクを実現するには、Custom URL SchemeとUniversal Linksのいずれかを使用します。

Custom URL Scheme

youtube://のようにアプリ固有のスキームを設定することができます。この固有なスキームをCustom URL Schemetといいます。
例えばyoutube://www.youtube.com/watch?v=BOeesPTK5Tcというリンクをyoutubeアプリをインストールしている端末で開くと、HikakinTVの動画画面に遷移されると思います。
ただyoutubeアプリがインストールされていないとエラーが表示されてしまいます。
また同じスキームを設定しているアプリが複数ある場合、意図したとおりにハンドリングされません。

Universal Links

Universal Linksはディープリンク機能に加え、アプリがインストールされていない場合は任意のWebサイトもしくはAppStoreへ遷移させることができます。
またドメインで一意性が担保されているので、リンクを奪い合うようなことも発生しません。
まだCustom URL Schemeを使用している場合は、早めにUniversal Linksに移行したほうが良さそうです。
ただAndroidでも同様の機能を実装したい場合は、AppLinksという別の技術要素を使わなければならずプラットフォームごとの対応が必要になってきます。またサーバー上にapple-app-site-accosiationを作成・配置する作業が煩わしいと思います。

そしてUniversal Linksの弱点を克服したものが、Firebase Dynamic Linksです。

Firebase Dynamic Links

Firebase Dynamic Linksは、アプリのインストール有無に関わらず、複数のプラットフォームで機能するリンクです。つまりプラットフォームごとの対応は不要ということになります。
またapple-app-site-accosiationの作成・配置が不要だったり(自動でやってくれる)、アナリティクスデータを集計してくれたりなどもします。ここまでいたれりつくせりなのに、料金は無料です。

Custom URL SchcmeとUniversal Links、Firebase Dynamic Linksについてまとめると以下のようになります。

実現方法 概要
Custom URL Schcme ディープリンキングできるが、アプリがインストールされていない場合、エラーが表示される。またリンクの衝突も発生する可能性があり、他のアプリに遷移が奪われる可能性もある。
Universal Links Custom URL Schcmeの欠点を克服したもの。ただAndroidで同様の機能を実現したい場合は、別途対応が必要となる。
Firebase Dynamic Links Universal Liksの機能を複数プラットフォームで対応できる。さらにリンクをタップした回数などの計測など以外のことも+αでやってくれる。

Dynamic Linksを作成してみる

Dynamic Linksを作成する方法はいくつもあるのですが、今回はFirebaseコンソール上から作成する手順について記載していきます。

  1. Dynamic Linksのコンソールから新しいダイナミックリンクをクリックしてください。
  2. 短縮URLのリンク設定にて、ユーザーに見せたいURLを入力してください。ドメインは変更不可なのですが、パス部分でどのようなURLなのか表現してください。ドメインを変更したい場合は別途対応が必要です。
  3. iOS、Android端末を使用中のユーザーがDynamic Linkをタップしたときの挙動を設定してください。多くの場合は、ディープリンクを iOS アプリで開くを選択することになると思います。
  4. 最後にその他オプションの設定後、`作成ボタンをクリックしてください。

独自のドメインをDynamic Linksのドメインとしたい場合はFirebase Hostingにドメイン登録後、メニューのURL 接頭辞を追加から独自ドメインのDynamic Linkを作成してください。

https://firebase.google.com/docs/dynamic-links/custom-domains?hl=ja

Dynamic Linksを受信する

1.インストールする

いずれかの方法でDynamic Linksをインストールしてください。

Cocoapods

Podfileに以下を追加し、pod installしてください。

pod 'Firebase/Analytics'
pod 'Firebase/DynamicLinks'

Carthage

Cartfileに以下を追加し、carthage updateしてください。

binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseDynamicLinksBinary.json"

https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md

SwiftPM

File -> Swift Packages -> Add package Dependencyから以下のようにhttps://github.com/firebase/firebase-ios-sdk.gitを入力します。

その後FirebaseAnalyticsFirebaseDynamicLinksにチェックを付けてインストールしてください。

FirebaseのSwiftPM対応はbetaなので問題が発生する可能性があります。

https://github.com/firebase/firebase-ios-sdk/blob/master/SwiftPackageManager.md

2.Associated Domainsにドメインを追加する

Associated Domainsに生成したリンクを追加してください。
applinks:を接頭辞とし、それ以降にDynamicLinkのドメインを入力してください。

また独自のドメインを利用している場合は、Info.plistに以下のkey/valueを追加してください。

<key>FirebaseDynamicLinksCustomDomains</key>
<array>
    <string>https://example.com/promos</string>
</array>

3.ディープリンクをハンドリングする

以降に示すコードで使用しているFirebaseDynamicLinksのversionは、7.1.0です。

1.受信処理の準備

AppDelegateapplication(_:didFinishLaunchingWithOptions:)に以下コードを追加してください。

import FirebaseDynamicLinks

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    FirebaseApp.configure()
    return true
}

2.URLをパースする

application(_:continue:restorationHandler:)にURLのパース処理を書き、抽出したディープリンクに応じて遷移したい画面を決定してください。

NSUserActivityは、ユーザーの行動に関連付けられたデータが含まれているオブジェクトであり、これを利用してiOSアプリでユーザーの行動を続行しています。
application(_:continue:restorationHandler:)は、ユーザーの行動を継続するためのデータが利用可能であることを通知するメソッドです。このデリゲートメソッドはUniversal Links専用ではないため注意してください。

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // NSUserActivityTypeBrowsingWebはUniversalLinksであることを示しており、
    // 他のアクティビティとUniversal Linksを区別しています。
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
    let url = userActivity.webpageURL else {
        return false
    }
    let handled = DynamicLinks.dynamicLinks().handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
        // 取得したディープリンクをもとに遷移先をハンドリングしてください。
        // URLComponents型に変換するとpathやqueryを取得しやすくなります。
        guard let deepLink = dynamiclink?.url,
        let component = URLComponents(url: deepLink, resolvingAgainstBaseURL: true) else {
	    return
	}
	print(component.path)
    }
    return handled
}

またアプリインストール時にcomgoogleapp://google/link?deep_link_id=abc123のようなCustom URL Schemeを受信、そしてリンクをパースしDynamic Linkを取得します。
Custom URL Schemeはapplication(_:open:options:)から取得できます。

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
    // 受信したURLSchemeからDynamicLinkを取得できない場合はnilとなります。
    guard let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) else {
        return false
    }
    return true
}

Push通知のペイロードにDynamicLinkが含まれている場合も、DynamicLinks.dynamicLinks().handleUniversalLinkでディープリンクを取得し、それをもとに遷移先を決定するようにしてください。

まとめ

これまでの手順によりDynamic Linkをタップすると、アプリがインストールしていない場合はAppStoreへ遷移、アプリがインストールされている場合はアプリを起動し、さらに特定の画面への遷移も可能になりました。Universal Linksだとapple-app-site-associationを置く場所を用意するなど個人的には少し面倒だなと感じていたことが、FirebaseDynamicLinksにより解決されたので良いサービスだなと思います。
また計測もできるので、サービスをグロースさせるためにも活用できそうです。

参考URL