Universal Links の実装と嵌まりどころなど

モバイルソリューション事業部の浮田です。

来週には iOS 10 の発表が行われる?時期となりましたが、
Universal Links 対応を行なったので手順と嵌まりどころなどをまとめてみました。

サーバ(Web)サイドの実装


apple-app-site-accosiation ファイルを作成する


どのアプリがどのような条件(パス)で Universal Links を行わせたいのかを次のように定義します。

{
"applinks": {
"apps": [],
"details": [
{
"appID": "9JA89QQLNQ.com.apple.wwdc",
"paths": [ "/wwdc/news/", "/videos/wwdc/2015/*"]
},
{
"appID": "ABCD1234.com.apple.wwdc",
"paths": [ "*" ]
}
]
}
}

次に、定義した内容を配置する際のファイルフォーマットですが、条件により提供できるファイルフォーマットが異なります。

- Web サイトは https をサポートしており、iOS 9 以降を対象としている場合
 署名の必要なし
- Web サイトは https をサポートしていない、または iOS 8 以降を対象としている場合
 署名の必要あり

ここで署名の必要がある場合、詳細は Apple の Developer サイトに記載されていますのでそちらを参照してください。

apple-app-site-accosiation を配置する


http(s)://domain/apple-app-site-accosiationでアクセスできるよう Web サイトにファイルを配置します。
この際、ファイルフォーマットの応じ適切な MIME-Type(Content-Type) が返されるよう留意してください。

- 署名されていない
 application/json
- 署名されている
 application/pkcs7-mime
また、iOS 9.3.1 以降は、http(s)://domain/.well-known/apple-app-site-associationへまずアクセスが行われるように変更が行われているため、404エラーが気になるようであればエイリアスを作成することおすすめします。

App Search API Validation Tool で確認する


Apple より確認のためのツールが提供されていますので、App Search API Validation Tool で対象の URL を入力し、対応状況を確認することができます。

Universal Links の項目が、PASSEDになっていればOKです。これでサーバサイドでの対応は完了です。

アプリケーション(iOS)サイドの実装


Associated Domains を有効にする


Apple の Developer サイトでAssociated Domainsを有効します。
対象の AppID を選択し、Associated Domainsを有効にし変更を完了してください。

次に、Xcode でAssociated Domainsの設定を行います。
プロジェクトで対象のターゲットを選択し、Capabilities -> Associated Domainsを有効にします。
その後、Domains にapplinks:{domain}を追加します。

実装する


UIApplicationDelegate プロトコルの application:continueUserActivity:restorationHandler: に実装を行います。

func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {

if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
let supported = true // userActivity.webpageURL が Universal Links に対応しているかを判定
if (supported) {
// 遷移処理など
}
else {
// サポートしていない URL は Safari へリダイレクトすることが推奨されている
if let url = userActivity.webpageURL as NSURL! {
application.openURL(url)
return false
}
}
}

return true
}

また、Universal Links を機能させるためにアプリケーションのプロセスを立ち上げる必要があった場合、application(_:didFinishLaunchingWithOptions:) のオプションにその内容が含まれていますので、こちらから Universal Links イベントの内容を取得することも可能です。

Firebase(Google) App Indexing にも対応しよう


iOS の場合、Universal Links を実装すればほぼ対応が完了したも同然です。
Firebase(Google) App Indexing SDK を追加して、対応を完了させてしまいましょう。
ここでは、Firebase App Indexing での対応を説明します。

コンソール上でプロジェクトを作成する


Firebase へアクセスし、必要であればサインアップ・プロジェクトの登録を行います。

プロジェクトにアプリを登録する


プロジェクトに iOS アプリを登録を行います。
ウィザードが表示されるので、手順通りに作業を進めていきます。

アプリで実装する


この段階でウィザードによってコアである Firebase SDK のインストールは完了しているかと思います。
引き続き、Firebase App Indexing SDK の追加を行います。

Podfile にFirebase/AppIndexingを追加します。

pod 'Firebase/AppIndexing'

コマンドを実行し、インストールを完了させます。

pod install

最後に、FIRApp.configure()の後に AppIndexing の初期処理を追加することで対応は完了です。

import UIKit
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
FIRAppIndexing.sharedInstance().registerApp({12345678}) // iTunes の Apple ID を指定する
return true
}
}


嵌まりどころなど注意点


appID Prefix に注意


appID Prefix の値は、オフィシャルなドキュメントでは team ID or App ID Prefix と書かれていますが、team ID と App ID Prefix の値が異なる場合は team ID を設定している場合は Universal Links は機能しませんでした。
その昔、App ID Prefix は追加することができたので、古参アプリを対応する場合は appID Prefix の値には気をつけてください。

同ドメインのページ遷移では Universal Links は自動有効にならない


iOS 9 リリース当初、試してみていて非常に嵌まりました。。
その場合、ページを引っ張ってみると幸せになれるかもしれません。

特定条件で同ドメインでの遷移なのに Universal Links が自動有効になる


通常の動作は先述した通りなのですが、どうやら新たにタブでページを開き、さらに http -> https とリダイレクト処理が行われると制約から外れ、Universal Links が自動有効になるようです。…これはバグでしょうか?

SFSafariViewController から Universal Links で呼び出すとステータスバーに何も表示されない


呼び出し元に戻るリンクが存在しないので不便に感じます。
Web サイトを表示するリンクもありません。

SFSafariViewController では Universal Links が必ず有効になる


Safari で自動有効をオフにしていても、SFSafariViewController では必ず Universal Links が呼び出されます。
また、自身で定義している Universal Links にも漏れなく反応しており、SFSafariViewController でページ遷移を行わせたいのにアプリに処理が戻されてしまいます。
調べてみましたが、SFSafariViewController で継続してページ遷移を行わせるような術はないようです。

開発中のアプリが突然起動する不可思議な事象に見舞われる


他のアプリで SFSafariViewController で Webページを 閲覧しようとすると、突然開発中のアプリが起動することがありました。
おそらく、SFSafariViewController を使用すると Safari のプロセスが呼び出され、メモリの関係でアーカイブされていたタブが復元されて Universal Links が動作しているのではないかと推測されます。

まとめ


サーバサイドで apple-app-site-accosiation ファイルの配置と、アプリサイドで既存の遷移処理を少し弄ってやれば対応できると想定していましたがそうではありませんでした。
何らかのご参考になればと思います。

この記事へのコメント