[iOS]iOS9から追加のUniversalLinks(ユニバーサルリンク)でディープリンク実装し、アプリの有無でアプリとマーケットにリダイレクトする
はじめに
UniversalLinksでディープリンクを実装し、リンククリックでアプリを起動する方法をメモします。ios9より対応しているため、それ以前のバージョンは考慮しません。(実際はカスタムURLを使うと実装が可能です。iOS9以前を対象ととする場合はバージョンにより切り分ける処理が、アプリ側もサーバ側も必要になります。)
やりたいこと
1)既にアプリがインストールされている場合はアプリを起動
2)アプリがインストールされていない場合はストアを起動(アプリのインストールを促す)
ドキュメント
https://developer.apple.com/jp/documentation/General/Conceptual/AppSearch/UniversalLinks.html
UniversalLinksについて
引用:
ユニバーサルリンクに対応すると、iOS 9ユーザがウェブサイトのリンクをタップしたとき、Safariを経由せず、インストール済みアプリケーションに直接遷移させることが可能になります。もし未インストールの場合はSafariが起動し、ウェブサイトが開きます。
iOS9より前のバージョンのUniversalLinks挙動
引用:
iOS 9.0よりも古いバージョンであれば、ユニバーサルリンクをタップするとSafariが起動し、リンク先ページが開きます。
新規アプリの場合はios9以前のバージョンは現時点で5%以下のため捨てて良いと思います。
https://developer.apple.com/support/app-store/
UniversalLinks実装について
UniversalLinksの実装にはアプリ側とサーバ側どちらも設定を行う必要があります。サーバ側のみ対応してもアプリ側で対応しないとディープリンクは有効に働きません。
サーバ側の実装:
1)apple-app-site-associationファイルの作成と設置
アプリ側の実装:
1)com.apple.developer.associated-domainsエンタイトルメントに該当するドメインのエントリを追加する
2)ディープリンクをハンドリング
[サーバ側] 1)apple-app-site-associationファイルの作成と設置
アプリとサーバで関連付けを行い信頼をあげるための処理を入れる必要があります。
apple-app-site-associationファイルを作成し、サーバに設置し、アプリ側でインストール時にダウンロードを行い中身の整合性チェックを行いセキュアな接続をしています。
引用:
apple-app-site-associationファイルは、ドメインごとに内容を変えて用意する必要があります。たとえばapple.comとdeveloper.apple.comには、それぞれ独立にapple-app-site-associationファイルを用意します。この2つのドメインは、提供するコンテンツが異なるためです。一方、apple.comとwww.apple.comは、同じコンテンツを提供するので、関連づけファイルも同じで構いません。ただし、両方にこのファイルを置く必要があります。iOS 9.3.1以降で動作するアプリケーションの場合、圧縮されていないapple-app-site-associationファイルのサイズは、署名済みファイルであるかどうかにかかわらず128KBを超えないことが要件になります。
apple-app-site-associationファイルにドメイン情報を設定します。
ファイルはjsonですが拡張子はつけるとうまく動作しないようです。
設定例:
{
“applinks”: {
“App”: [],
“details”: [
{
"appID": "9JA89QQLNQ.com.apple.wwdc",
"paths": [ "/wwdc/news/", "/videos/wwdc/2015/*"]
},
{
“appID”: “ABCD1234.com.apple.wwdc”,
“paths”: [ "*" ]
}
]
}
}
引用:apple-app-site-associationファイル記述に関する説明文
apple-app-site-associationファイルには「apps」キーが必須です。その値は、リスト6-1のように、空の配列でなければなりません。detailsキーの値は辞書の配列で、ウェブサイトがサポートするアプリケーションごとに辞書を用意します。システムは辞書が配列中に現れる順序に従ってアプリケーションを照合します。その結果、ウェブサイトのパスによって、処理を引き受けるアプリケーションが決まります。
アプリケーションごとに用意する辞書には、appIDキーとpathsキーが必要です。appIDキーの値はチームIDまたはApp IDの接頭辞であり、このプレフィックスの後ろにバンドルIDが付加されます(appIDの値は、アプリケーションのビルド後、アプリケーションのエンタイトルメントに含まれている“application-identifier”キーに関連づけられているものと同じ値です)。pathsキーの値は、ウェブサイト中のどのパスを当該アプリケーションが処理し、どのパスを当該アプリケーションには関連づけないかを表す文字列の配列です。ユニバーサルリンクとして処理しない領域を指定するには、パス文字列の先頭に“NOT ”を付加します(Tの後ろには空白文字を入力)。たとえば、リスト6-1に示したapple-app-site-associationファイルの場合は、paths配列を以下のように書き換えることで、ウェブサイトの/videos/wwdc/2010/*領域がユニバーサルリンクとして処理されないように設定できます。
“paths”: [ "/wwdc/news/", "NOT /videos/wwdc/2010/*", "/videos/wwdc/201?/*"]
paths配列に含まれている個々のパスは、記述されている順に評価され、肯定または否定の検索文字列に一致するものが見つかった時点で評価が中止されます。したがって、優先度の高いパスを低いパスよりも先に記述する必要があります。なお、照合するのはURL中の「パス」部分だけで、クエリ文字列、フラグメント識別子など、その他の部分は無視します。apple-app-site-associationファイルには、ウェブサイトのパスをさまざまな方法で記述できます。その例をいくつか示します。
*を使って、ウェブサイト全体を指定する。
具体的なURL(たとえば/wwdc/news/)を記述して、リンクを個別に指定する。
具体的なURLに*を付加して(たとえば/videos/wwdc/2015/*)、ウェブサイトの特定のセクションを指定する。
任意の部分文字列に合致する「*」のほか、任意の1文字に合致する「?」も指定できます。この2つのワイルドカードをひとつのパスの中で用い、「/foo/*/bar/201?/mypage」のように記述することも可能です。
[アプリ側] 1)com.apple.developer.associated-domainsエンタイトルメントに該当するドメインのエントリを追加する
サーバとの関連付けのため、ドメインをエントリします。
xcodeのcapabilitiesから設定します。
引用:
com.apple.developer.associated-domainsエンタイトルメントに、アプリケーションがユニバーサルリンクとして扱うドメインの一覧を記述します。Xcode上で、「Capabilities」タブの「Associated Domains」セクションを開き、該当する各ドメインのエントリを追加してください。applinks:を接頭辞として付加し、たとえばapplinks:www.mywebsite.comとします。この一覧に記述するドメインの数は、20〜30以下に抑えてください。
関連するドメインのすべてのサブドメインをパターンマッチングの対象にするには、個々のドメイン名の先頭に*.を接頭辞として付けることで、ワイルドカードを指定します(ピリオド必須)。ドメイン名のパターンマッチングの基準になるのは、applinksエントリに含まれている最長の部分文字列です。たとえば、applinks:*.mywebsite.comとapplinks:*.users.mywebsite.comというエントリを指定した場合、emily.users.mywebsite.comドメインについては、長いほうの*.users.mywebsite.comエントリとのパターンマッチングが実行されます。*.mywebsite.comというエントリの場合、アスタリスクの後ろにピリオドがあるため、mywebsite.comに一致しているとは見なされないことに注意してください。*.mywebsite.comとmywebsite.comのどちらについてもパターンマッチングを有効にするには、applinksエントリをそれぞれ別に記述する必要があります。
[アプリ側] 2)ディープリンクをハンドリング
アプリでディープリンクを取得しドメインにより処理を切り分けます。
引用:
HandoffにUIApplicationDelegateメソッドを採用して(特にapplication:continueUserActivity:restorationHandler:)、アプリケーションでリンクを受信して適切に処理できるようにします。
実装コード例
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
let webpageURL = userActivity.webpageURL! // userActivity.webpageURLのurlを取得し、ドメイン判定を行い処理を切り分ける。サポートしていない場合はsafariへリダイレクト処理を入れるのが慣例
}return true
}
アプリをインストールしていない場合にStoreへ遷移するには
Universal Linksは直接Storeへの遷移はできないため、一旦、未インストール用のページをサーバで用意して、そちらに遷移し、そこのファイル内でStoreへ遷移させることが必要になります。
<a href=”itmss://itunes.apple.com/us/app/myapp/id[アプリID]?ls=1&mt=8″></a>
アプリIDにiTunesサイトのリンクのIDを入れると遷移します
参考
http://qiita.com/mono0926/items/2bf651246714f20df626
https://developer.apple.com/jp/documentation/General/Conceptual/AppSearch/UniversalLinks.html
その他おすすめの備忘録
- [Android]MACでフィンガープリント(SHA1)を取得する
- [iOS]アップルの64bit対応/iOS8対応の対処方法について参考資料
- 本日の勉強会レポート(SEO勉強会 / webクリエイターが知っておきたいSEOのツボ!!)
- [Android]Activity#runOnUiThreadメソッドで簡単スレッドハンドリング
- GooglePlayマーケットリリースのカメラアプリの12/25統計情報
- [iOS]2015年5月13日iTunes Connectにアプリのアナリティクス(App Analytics)機能[ベータ版]が実装されました
- [iOS][Android]iOS/Android開発者が知ってた方が良いサイト一覧
- [Android]アプリリリース ソーシャルタイマー 〜 SNS予約投稿 〜
- [iOS]WWDC2017発表のiOS11から追加された新API(Framework)について
- [jQuery]匿名クラスでクロージャを解決する方法をメモ for clickメソッド
coffee-break
Don't write code that useless.
1日5杯はコーヒー、カフェオレ飲みます。狭心症のため安静にします☆松本 雄貴
Kotlinでサービスリリース目指す!
iOSでチャットアプリ作成中。自然言語解析LSIを習得中
Mac / Android・iOS / Rails / Oracle
2017年 Lpic L2取得
2012年 Android技術者資格取得
2010年 OracleMasterGold10g取得
2008年 CCNAQiitaもたまに投稿
https://qiita.com/y-matsumoto東京近郊で常駐開発探してる方はこちらよりご連絡ください
SES企業でパートナー会社を探している企業様はこちらよりご連絡ください
スプリットカメラ iOS / Android
音声認識で聞いた日付から曜日当てアプリ Android
ソーシャルタイマー Android
カテゴリー
- ActiveRecord (2)
- Android (52)
- AndroidStudio (10)
- Ansible (1)
- AWS (1)
- Bash (18)
- Blog (7)
- BootStrap (1)
- CentOS (16)
- Chef (1)
- css (2)
- Eclipse (5)
- error (1)
- Facebook (2)
- Firebase (1)
- FuelPHP (16)
- Git (22)
- GitHub (3)
- Gradle (2)
- GraphAPI (1)
- Grunt (1)
- heroku (2)
- illustrator (1)
- iOS (17)
- Java (4)
- Jenkins (1)
- jQuery (3)
- Kotlin (2)
- Mac (22)
- nginx (1)
- Node.js (3)
- peco (1)
- php (5)
- Python (1)
- Rails (16)
- Ruby (11)
- shell (1)
- SNS (1)
- Swift (2)
- tmux (2)
- Vagrant (6)
- Vim (6)
- windows (2)
- WordPress (3)
- zsh (4)
- フリーランス (1)
- ライブラリ (1)
- 勉強会 (2)
- 宣伝 (1)
- 未分類 (2)
最近の投稿
- [MAC]HighSierraでgitプッシュエラー「Unable to negotiate with xxx.xxx.xxx.xxx port xx: no matching cipher found. Their offer: aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se fatal: Could not read from remote repository.」
- [iOS]iOS11からFacebook,Twitter連携(シェアなど)廃止の対応方法
- [iOS]速報2017AppleSpecialEventのiOS11、iPhone8など発表内容について
- [iOS][Firebase]The default Firebase app has not yet been configured. Add `[FIRApp configure];
- [iOS]2017年9月リリースのiOS11で開発者が対応するべきこと
- 今人気の現金化サービスCASH(キャッシュ)を使ったレビュー
- [Pandoc][Mac]pandocでmarkdownからwordファイル作成
- [Android]映画サマーウォーズの聞いた日付(誕生日)から曜日当てをアプリ音声認識で簡単に実現
- [Android]起動しているActivityを取得するadb shell コマンド
- [Android][Kotlin]kotlin学習で参考になるサイト一覧
2023年12月 月 火 水 木 金 土 日 « 5月 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 アーカイブ
- 2018年5月
- 2017年9月
- 2017年8月
- 2017年7月
- 2017年6月
- 2017年5月
- 2017年2月
- 2017年1月
- 2016年12月
- 2016年7月
- 2016年6月
- 2016年1月
- 2015年12月
- 2015年11月
- 2015年10月
- 2015年9月
- 2015年8月
- 2015年7月
- 2015年6月
- 2015年5月
- 2015年4月
- 2015年3月
- 2015年2月
- 2015年1月
- 2014年12月
- 2014年11月
- 2014年6月
- 2014年5月
- 2014年4月
- 2014年3月
- 2014年2月
- 2014年1月
- 2013年12月
- 2013年11月
- 2013年9月
- 2013年8月
- 2013年7月
- 2013年6月
- 2013年5月
- 2013年4月
- 2013年3月
- 2013年2月
- 2013年1月
- 2012年12月
- 2012年10月
- 2012年5月
- 2010年6月
エントリ