Universal Linksを試してみました。関連づけファイル(apple-app-site-association)はS3に置きました。

ios

1 はじめに

先日書いた、Custom URL Schemeを使用すると、特定のスキームでアプリを起動することが可能です。
[iOS] ディープリンク(Custom URL Scheme)でアプリを起動する

しかし、Custom URL Schemeは、そもそもアプリがインストールされていないと何も出来ません。また、スキームは、他のアプリとの競合を確実に回避することもできませんでした。

今回は、iOS 9以降で利用可能な、Universal Linksを試してみました。Universal Linksは、サーバと連携して動作しており、関連付けのファイルをWeb上に置く必要がありますが、今回は、Amazon S3を使用しました。

Universal Linksを実装する作業は、概ね次のとおりです。

  • 関連づけファイル(apple-app-site-association)をWeb上に配置
  • Associated Domainsの追加
  • アプリ起動時のハンドリング

なお、作成したサンプルでの名前等は、次のようになっています。

  • アプリのBundle Identifire jp.ne.sapporoworks.ULSample
  • Amazon S3のバケット名 unversal-links-backet
  • 使用するドメイン universal-links-bucket.s3.amazonaws.com

2 関連づけファイル(apple-app-site-association)をWeb上に配置

(1) apple-app-site-accosiation

apple-app-site-associationは、次のようなJSON形式のファイルです。(拡張子は付けません)

{
  "applinks": {
       "apps": [],
        "details": [
           {
               "appID":"T3xxxxxxVX.jp.ne.sapporoworks.ULSample",
               "paths":[ "*" ]
           }
         ]
    }
}

appsは、必須ですが、何も指定しません。appIDは、「Team名」+「アプリのBundle Identifire」です。 pathsには、アプリに遷移させるURLを指定しますが、今回は、全てを意味するワイルドカードを設定しました。

(2) サーバへの配置

サーバへの配置では、下記の要件があります。

  • httpsでアクセスできる(httpの場合は署名が必要)
  • ドメインのルートに配置し、リダイレクトなしでアクセスができる
  • Content-Typeはapplication/json(署名がある場合は、application/pkcs7-mime)

今回は、S3に配置してhttpsでアクセスすることで、この要件をクリアしました。

S3にバケット(名前を「universal-links-bucket」としました)を作成し、そこに、index.html及びapple-app-site-associationを置きました。 そして、apple-app-site-associationContent-Typeapplication/jsonに設定しています。

003

上記のバケットで、Static Web Hostingを有効にし、必要なPermitionを設定すると、 下記のURLでアクセス可能になります。

https://universal-links-bucket.s3.amazonaws.com/

[ https://{バケット名}.s3.amazon.com/{ファイル名} ]

下の図は、Chromeを使用して、httpsで、ドメインのトップからapple-app-site-associationにアクセスできることを確認しているようすです。

004

念のため、curlでも確認してみます。 リダイレクトなしでアクセスでき、Content-Typeもapplication/jsonになっているのが分かります。

$ curl -v https://universal-links-bucket.s3.amazonaws.com/apple-app-site-association
*   Trying 52.216.225.128...
* Connected to universal-links-bucket.s3.amazonaws.com (52.216.225.128) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: *.s3.amazonaws.com
* Server certificate: DigiCert Baltimore CA-2 G2
* Server certificate: Baltimore CyberTrust Root
> GET /apple-app-site-association HTTP/1.1
> Host: universal-links-bucket.s3.amazonaws.com
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< x-amz-id-2: KynYJJGxI/TbRexY8Wv/CW+GZBShXCHoMyLeFVugZZcuRdFllwIiJg5yh/dLtyWYjIJxDidyLyE=
< x-amz-request-id: BA6551DC7411FD62
< Date: Tue, 07 Feb 2017 07:33:01 GMT
< Last-Modified: Tue, 07 Feb 2017 07:32:52 GMT
< ETag: "5b7786baaa403f1308b04e22cd64946b"
< Accept-Ranges: bytes
< Content-Type: application/json
< Content-Length: 201
< Server: AmazonS3
<
{
    "applinks": {
        "apps":[],
        "details":[
            {
                "appID":"T3xxxxxxVX.jp.ne.sapporoworks.ULSample",
                "paths":["*"]
            }
        ]
    }
}
* Connection #0 to host universal-links-bucket.s3.amazonaws.com left intact

3 Associated Domainsの追加

CapabilitiesAssociated Domainsを有効(ON)にし、Amazon S3で準備したドメインを設定します。

記述要領は、applinks:ドメイン名です。

applinks:universal-links-bucket.s3.amazonaws.com

005

記事によっては、先に、Associated Domainsを有効にしたAppIDを作成するような紹介も有りましたが、現在のXcodeでは、自動で作成されるので、必須作業ではないようです。

下記は、自動的に生成されたAppIDです。名前が、XCで始まっています。 006

実は、ここまで出来たら、Safariからアプリへの遷移は可能になっています。

https://universal-links-bucket.s3.amazonaws.com/index.htmlへのリンクをタップすると、Webページは表示されずに、アプリが直接起動します。

012 013

Safariのアドレスバーにhttps://universal-links-bucket.s3.amazonaws.com/index.html を入力した場合は、直接アプリは起動せず、当該ページが表示されますが、少し下にスクロールすると図のようなボタンが表示され、これをタップすると、アプリが起動します。

007

4 アプリ起動時のハンドリング

Universal Linksでアプリが起動された場合、そのURLは、application(_:continue:restorationHandler:)で取得することが可能です。

NSUserActivitywebpageURLにそのまま入ってますので、これに応じてアプリの振る舞いを実装できます。

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

上記のコードは、URLをログに表示していますが、例えば、下記のようなリンクから遷移した場合、図のようになっているのが確認できます。

<a href=https://universal-links-bucket.s3.amazonaws.com/path/file?key=value>リンク</a>

018

5 テストツール

関連付けファイルの内容をデバッグするために、テストツールが公開されています。
App Search API Validation Tool

こちらで、apple-app-site-associationの設置状況が確認可能です。

002

しかし、アプリが未公開の状態では、下記のようにPASSEDにはなりませんので注意が必要です。

001

6 シミュレーター

一部の記事で、シミュレーターでは動作確認できないような記載を見かけたのですが、特に問題なく動作しています。(公式のドキュメントにも、特に記述はありませんでした)

[2017/02/11追記] すいません、iOS 9のシュミレータでは、動作しないようです。

009 010 008

7 Chromeでの動作

リンク先への遷移は、Chromeからでも、動作しました。そして、戻り先もChromeになっています。

015 014

しかし、アドレスバーに直接入力した場合は、Webページが表示されるだけで、下スクロールしても、アプリを開くボタンは表示できません。

017 016

8 最後に

今回は、Universal Linksを試してみました。この技術は、iOS 9以降でしか動作しないので、先のカスタムリンクとの連携が必要不可欠だと思います。次回は、その辺を掘り下げて確かめてみたいと思います。

9 参考リンク


Apple Refelence Support Universal Links
Apple プログラミングリファレンス ユニバーサルリンクへの対応
URLスキーム・独自ディープリンク実装に代わる、Universal Links(iOS 9で導入)でより良いUXを実現
Universal Links の実装と嵌まりどころなど
【iOS9】Universal Links を試す
JACK'S PLACE
[iOS] ディープリンク(Custom URL Scheme)でアプリを起動する

AWS Cloud Roadshow 2017 福岡