ディープリンク技術についてまとめてみた


# 概要
ディープリンクとは、スマホアプリの特定のコンテンツヘ、直接遷移するリンクのことを指します。
「○○アプリを起動する」というようなボタンやリンクを押すと、その対象のアプリが起動する、
といったものを実現させたい時に、この技術を使います。

iOSにてディープリンクを実現するための技術として、
「Custom URL Scheme」や「Universal Links」というものがあります。
今日は、それらがどういうもので、どこが違うのかという点や、それぞれの実装方法をまとめてみました。

# Custom URL Scheme
## 概要
- ディープリンク技術の１つ
- `cm-app://` のような任意のURL Schemeを決める
- そのURLが開かれた時に、アプリが起動するように実装する
- iOS6.0~対応

## どういうユーザー体験になるか
`cm-app://hogehoge` というリンクを踏むと・・・

### アプリがインストールされている場合
- アプリ起動に関するダイアログが表示される
- 「Open」等を選択するとアプリが起動する 

### 未インストールの場合
- エラーになり、アプリは起動しない
- **ストアに飛ばしたり等したい場合は、Webサイトorアプリで、別途実装が必要**

## 実装方法
#### Info.plistにURL Schemeを定義するだけ
<img width="663" alt="スクリーンショット 2017-10-17 22.48.33.png (269.7 kB)" src="https://img.esa.io/uploads/production/attachments/4518/2017/10/17/23519/3558ebc1-73ca-4467-870d-9595555849c9.png">

#### そうすると、こんな感じで起動することができる
<img width="524" alt="スクリーンショット 2017-10-17 22.51.43.png (257.6 kB)" src="https://img.esa.io/uploads/production/attachments/4518/2017/10/17/23519/a0d112f5-8dd9-441c-850e-98d650dfd53e.png">

#### 起動後の処理を出し分けることも出来る
どのようなURLから起動されたかを取得することが出来るので、
それによって処理を出し分けることが出来る。
（例）
cm-app://setting → 設定画面を開く
cm-app://profile → プロフィール画面を開く
 
```
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    print("url : \(url.absoluteString)")
    print("scheme : \(url.scheme!)")
    print("host : \(url.host!)")
    print("port : \(url.port!)")
    print("query : \(url.query!)")
    return true
}
```

```
url : cm-app://hostname:8080/test?name=taro
scheme : cm-app
host : hostname
port : 8080
query : name=taro
```


# Universal Links
## 概要
- Custom URL Schemeの上位互換（だと私は思っている）
- 特定のHTTP or HTTPS のURLをアプリと紐付ける
	- クライアントに、紐付けたいURLを設定する
	- サーバー上に、クライアントの情報を記載した設定ファイルを設定する
- iOS9.0~対応

## どういうユーザー体験になるか
`https://sample.jp/news/index.html` というリンクを踏むと・・・
### アプリがインストールされている場合
- アプリが起動する
- **ダイアログは表示されず、シームレスにアプリ起動**

### 未インストールの場合
- そのURLが指定するコンテンツが開かれる
- **未インストールの場合向けの実装はいらない**

## 実装方法
### クライアント
#### 1. Associated Domains を追加して、
- Domains：`applinks:hostname`（例 : `applinks:sample.jp`）
- ここを設定すると、自動的にhoge.entitlementsが編集される

<img width="655" alt="スクリーンショット 2017-10-17 23.56.04.png (165.8 kB)" src="https://img.esa.io/uploads/production/attachments/4518/2017/10/17/23519/5a8a5ba4-5c56-48ce-9650-9154b7eb2322.png">



#### 2. Provisioning Profileを更新するだけ
<img width="661" alt="スクリーンショット 2017-10-17 23.56.14.png (213.1 kB)" src="https://img.esa.io/uploads/production/attachments/4518/2017/10/18/23519/dd510f11-6945-4f7d-96a2-65ec0d422c6f.png"> 

#### 3. 起動後の処理を出し分けることも出来る
こちらでも、どのようなURLから起動されたかを取得することが出来るので、
それによって処理を出し分けることが出来る。

```
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
        print(userActivity.webpageURL!)
    }
    return true
}
```

### サーバー
#### 設定ファイルを置くだけ
  - `https://hostname/apple-app-site-association` or `https://hostname/.well-known/apple-app-site-association`（ **ファイル名に `.json` はつけない**）
  - アプリの情報としては、appID（TeamID + Bundle Identifier）が必要
  - pathのフィルタリングが出来る

```
{
    "applinks": {
        "App": [],
        "details": [
            {
                "appID": "9JA89QQLNQ.com.apple.wwdc",
                "paths": [ "/wwdc/news/", "NOT /videos/wwdc/2015/*"]
            },
            {
                "appID": "TeamID.bundleIdentifier",
                "paths": [ "*" ]
            }
        ]
    }
}
```

## セキュリティ面でも優れている
- Custom URL Schemeでは、対象のディープリンクを、他のアプリが捕捉することが可能だった
- Universal Linksでは、以下の3点により、その点が解決されている

### 固有性
- 標準的なHTTPやHTTPSのウェブサイトへのリンクを使う
- 他アプリから同一のものを指定することはできない

### 安全性
- サーバ上の設定ファイルによって、このアプリが当該URLを開いても問題ないことを確認する
- 対象サーバに設定ファイルをアップロードできるのは、対象の開発者だけなので、 ウェブサイトとアプリケーションとの関連づけは安全なものになる

### 非公開性
- 他のアプリケーションがインストール済みか否か確認せずに、特定のアプリケーションに対して通信できる

## トラブルシューティング
### アプリが起動しない
- **サーバー側の設定ファイルのアプリ情報の間違いを疑おう！**
- アプリインストール時に、紐付けが行われる
- インストール時のログを見よう
- どういうアプリ情報で、サーバーへ確認しに行ってるかが分かる

#### ログを見る方法
- Xcode > Window > Device and Simulators
- キーワード：`swcd`

![Xcode6DeviceConsole.png (302.8 kB)](https://img.esa.io/uploads/production/attachments/4518/2017/10/18/23519/eb12eadd-2bf7-4ced-9ae8-4abc759a9076.png)

### iOS9.1だけアプリ起動しない
- `https://hostname/apple-app-site-association` と `https://hostname/.well-known/apple-app-site-association`の両方に設定ファイルを置こう
- 基本はどちらかでいいが、iOS9.1はルート直下しか見てくれないらしい


# まとめ
Universal Linksの方が、ちょっとだけ実装が面倒な感じがしますが、
そのコスト以上の恩恵がたくさん受けられます。
食べログだったり、クックパッドだったり、Web上のコンテンツとアプリを
密接につなげたい場面で、特に活用されているようです。

Androidでも似たような技術で、Digital Asset Linksというものがあったりします。
ディープリンク技術を上手く活用して、更なるUXの高みを目指していきましょう！

アドベントカレンダーも明日で最後ですね！トリの方、よろしくお願いします！！