【IOS】Univarsal Linksでアプリが起動しない
解決したいこと
swiftでUnivarsal Linksを用いてURLリンクをタップしたらアプリが起動する機能を実装しようとしています。
発生している問題・エラー
Univarsal Linksの実装に必要な以下手順を踏みましたが、
実機にアプリをインストールした後apple-app-site-association
を配置したFirebase HostingのURLリンクをタップしてもアプリが起動しませんでした。
何か他に確認が必要な箇所、漏れている手順などありますでしょうか?
<Univarsal Links実装手順>
①Apple Developerにて対象のAppIDに「Associated Domains」チェックを入れる
(AppIDの修正に伴いProvisioning Profileも更新)
②AppDelegate.swiftにapplication(_:continue:restorationHandler:)
を追加
③Firebase Hostingの/.well-known
ディレクトリに以下apple-app-site-association
を配置してデプロイ
public
|_ index.html
|_ .well-known
|_ apple-app-site-association
④Xcodeのアプリ対象TargetのCapabilityに「Associated Domains」を追加して、
applinks:<デプロイしたFirebase Hostingのドメイン>
を設定
⑤アプリをインストールする実機の[設定]->[デベロッパ]->[Associated Domains Development]をONにする
⑥実機にアプリをインストールしたあと、以下コマンドでCDNにapple-app-site-association
が反映されているか確認(HTTP/1.1 200 OK
、Content-Type: application/json
が返ってきていること)
curl -v https://app-site-association.cdn-apple.com/a/v1/<デプロイしたFirebase Hostingのドメイン>
該当するソースコード
・apple-app-site-association
{
"applinks":
{
"details":
[
{
"appIDs":
[
"[チームID].[アプリのバンドルID]"
],
"components":
[
{
"/": "*",
"comment": "すべてのパスを対象にする"
}
]
}
]
}
}
・firebase.json
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log"
],
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint",
"npm --prefix \"$RESOURCE_DIR\" run build"
]
}
],
"hosting": {
"public": "public",
"appAssociation": "NONE",
"rewrites": [ {
"source": "**",
"destination": "/.well-known/apple-app-site-association"
} ],
"headers": [
{
"source": "/.well-known/apple-app-site-association",
"headers": [
{"key": "Content-Type", "value": "application/json"}]
}
]
}
}
・AppDelegate.swift
//
// AppDelegate.swift
// FreTre
//
import UIKit
import FirebaseCore
import UserNotifications
import FirebaseAuth
import FirebaseFirestore
import FirebaseMessaging
import IQKeyboardManagerSwift
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
signInApp()
Messaging.messaging().delegate = self
setupIQKeyboard()
registarRemoteNotification(application: application)
return true
}
func setupIQKeyboard(){
let keyboardManager = IQKeyboardManager.shared
keyboardManager.enable = true
keyboardManager.keyboardDistanceFromTextField = K.keyboardDistance
keyboardManager.enableAutoToolbar = false
keyboardManager.shouldResignOnTouchOutside = true
}
func registarRemoteNotification(application:UIApplication){
if #available(iOS 10.0, *){
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert], completionHandler: {(granted, error) in
if (granted)
{
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
else{
//Do stuff if unsuccessful...
}
})
}
else { //If user is not on iOS 10 use the old methods we've been using
let notificationSettings = UIUserNotificationSettings(
types: [.badge, .sound, .alert], categories: nil)
application.registerUserNotificationSettings(notificationSettings)
}
}
func signInApp(){
Auth.auth().signInAnonymously { resutl, error in
if let error = error {
print(error.localizedDescription)
}else{
print("succes login!")
}
}
}
func updateFmcToken(teamId: String, teamUUID: String, fmcToken: String){
let updateData = [K.FStore.member_Id:K.uid,K.FStore.token: fmcToken] as! [String:Any]
Firestore.firestore().collection(K.FStore.c_Tokens).document(teamUUID).collection(K.FStore.subc_TokenMember).document(K.uid).setData(updateData) { error in
if let error = error{
print(error.localizedDescription)
return
}else{
print("success update fmcToken")
return
}
}
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
print("open")
return true
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
print("open")
return true
}
// remote notificationの受信メソッド
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) async -> UIBackgroundFetchResult {
// Print full message.
print(userInfo)
return UIBackgroundFetchResult.newData
}
}
// MARK: -extention for Firebase Messaging delegate method
extension AppDelegate:MessagingDelegate{
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("fcmToken:\(fcmToken!)")
guard let fmcToken = fcmToken else { return }
UserdefaultsManager.setString(value: fmcToken, key: K.UserD.fmcToken)
if let teamId = UserdefaultsManager.getString(key: K.UserD.teamId), let teamUUID = UserdefaultsManager.getString(key: K.UserD.teamUUID) {
updateFmcToken(teamId: teamId, teamUUID: teamUUID, fmcToken: fmcToken)
}
}
}
// MARK: - extension for notification delegate method
extension AppDelegate:UNUserNotificationCenterDelegate{
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions {
let userInfo = notification.request.content.userInfo
// Print full message.
print(userInfo)
// Change this to your preferred presentation option
return [[.badge,.sound]]
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
let userInfo = response.notification.request.content.userInfo
// With swizzling disabled you must let Messaging know about the message, for Analytics
Messaging.messaging().appDidReceiveMessage(userInfo)
// Print full message.
print(userInfo)
}
}
自分で試したこと
・apple-app-site-association
をルート直下にも配置
・適当なサイトにUnivarsal LinksのURLのリンクを埋めてそこからUnivarsal Linksを起動してみる
・AASA VALIDATORで対象のUnivarsal Linksのテストを実施して問題ないことを確認
・Provisioning Profileが「Associated Domains」を設定したAppIDと紐付いているか確認
・実機の[設定]->[デベロッパ]->[UNIVERSAL LINKS]->[Diagnostics]にてFirebase HostingのURLを検証し問題ないことを確認
・entitlementsファイルのTarget Membershipにチェックが入っていること、
CapabilityのAssociated Domainsに追加した値と同じ値が設定されていることを確認
環境
実機
バージョン:IOS16.3.1
機種:iPhone SE(第2世代)
Xcode
バージョン:14.3