如何设置关联域/通用链接
How to setup Associated Domains / Universal Links
我试图在访问 www.example.com/success as well as show a banner when visiting the homepage www.example.com.
时将用户重定向到已安装的应用程序
在我目前的植入中,url 不会重定向和打开应用程序,网站也不会显示横幅。
我正在按照此处找到的文档进行操作 https://developer.apple.com/documentation/safariservices/supporting_associated_domains
我的网站是一个简单的 create-react-app
,主页由 Firebase 托管。
我做了以下事情:
- 将关联域添加到签名和功能 - applinks:website.com/success
- 添加
apple-app-site-association
个文件到/public/
- 修改firebase.json文件
- Link 到 index.html
中的文件
我用什么来验证:
https://branch.io/resources/aasa-validator/
https://search.developer.apple.com/appsearch-validation-tool
通过添加www.example.com/success link 到注释并打开进行测试,它总是在safari 中打开。我也尝试过重新安装应用程序并重新启动 phone.
Apple API 验证
我已将具有关联域的新应用程序版本上传到商店
Branch.io
{
"applinks": {
"apps": [],
"details": []
}
}
访问时www.example.com/apple-app-site-association
{ "activitycontinuation": { "apps": [ "team.com.example.com" ] },
"applinks": { "apps": [], "details": [ { "appID":
"team.com.example.com", "paths": [ "/", "/", "/success", "/success/",] }, "webcredentials": { "apps": [
"team.com.example.com" ] } }
apple-app-site-association
{
"activitycontinuation": {
"apps": [
"team.com.example.com"
]
},
"applinks": {
"apps": [],
"details": [
{
"appID": "team.com.example.com",
"paths": [
"/",
"/*",
"/success",
"/success/*",
]
},
]
},
"webcredentials": {
"apps": [
"team.com.example.com"
]
}
}
Index.html
<link rel="apple-app-site-association file" href="%PUBLIC_URL%/apple-app-site-association">
<link rel="apple-app-site-association file" href="/apple-app-site-association">
<meta name="App" content="app-id=XXX, app-argument=https://apps.apple.com/US/app/APP/idXXX, affiliate- data=optionalAffiliateData">
Firebase.json
{
"hosting": {
"public": "public",
"headers": [
{
"source": "/apple-app-site-association",
"headers": [
{
"key": "Content-Type",
"value": "application/json"
}
]
}
],
"appAssociation": "NONE"
}
}
设备控制台
安装应用程序时,我在 Xcode 中监视设备控制台,查看 swdc
进程日志以查找与关联域或请求相关的任何内容。这是我找到的一些;
Error getting enterprise-managed associated domains data. If this
device is not enterprise-managed, this is normal: Error
Domain=SWCErrorDomain Code=1701 "Failed to get associated domain data
from ManagedConfiguration framework."
UserInfo={NSDebugDescription=Failed to get associated domain data from
ManagedConfiguration framework., Line=298, Function=}
Entry { s = applinks, a = , d = au….ub….com, ua = unspecified,
sa = approved } needs its JSON updated because the app PI changed
https://developer.apple.com/library/archive/qa/qa1916/_index.html
apple-app-site-association
中需要一个appID:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "XXXXXXXXXX.com.example.UniveralLinks",
"paths": ["*"]
}
]
}
}
applinks 标签确定哪些应用程序与网站相关联。将 apps 值保留为空数组。在 details 标签内是一个字典数组,用于 linking appIDs 和 URL 路径。为简单起见,您使用 * 通配符将此网站的所有 link 与 UniversalLinks 应用相关联。您可以将路径值限制为特定文件夹或文件名。
appID 由您的团队 ID 和应用程序的 bundle ID 组成,但您需要为自己的帐户使用标识符。
当您创建 Apple 开发者帐户时,Apple 会为您分配一个团队 ID。您可以在 Apple 开发人员中心找到它。登录网站,单击会员资格,然后在会员信息部分查找团队 ID。
现在您有了 apple-app-site-association,必须将它上传到 Web 服务器。
您 必须对网站具有“写入权限” 才能执行此操作。确保您正确设置了 apple-app-site-association
文件(在您的网络服务器上的根目录或 .well-known/
中,并且没有重定向)。
您还必须向 iOS 应用程序添加适用于通用 linking 的适当权利。
如果您使用 Xcode:
- Select 项目。
- Select目标。
- Select 功能选项卡。
- 滚动到并打开关联域。
然后您可以添加例如applinks:www.mywebsite.in
在“功能 -> 关联域”下。
或者在您的权利文件中,您可以添加如下内容:
<key>com.apple.developer.associated-domains</key>
<array>
...
<string>applinks:www.mywebsite.in</string>
...
</array>
处理通用链接:
现在应用程序和网站正式相互了解,应用程序需要的只是在调用时处理 link 的代码。
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?
) -> Void) -> Bool {
// 1
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL,
let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return false
}
// 2 // dig out component for deepLinking reference.
if let component = ItemHandler.sharedInstance.items
.filter({ [=12=].path == components.path}).first {
//handle navigation to page indicated by component
return true
}
// 3
if let webpageUrl = URL(string: "http://universal-links-final.example.com") {
application.open(webpageUrl)
return false
}
return false
}
每当用户点击与应用程序相关的通用 link 时,iOS 就会调用此方法。以下是每个步骤的作用:
首先,您验证传入的 userActivity 是否具有预期的特征。最终,您想要获取 activity 的路径组件。否则,您 return false 表示该应用无法处理 activity。
使用该路径,您可以查找与其匹配的已知视图控制器。如果找到一个,则为它显示视图控制器并且 return 为真。
如果找不到与路径匹配的视图控制器,则指示应用程序打开 URL,它将使用默认的系统应用程序代替——很可能是 Safari。你在这里也 return false 表示应用程序无法处理这个用户 activity.
首先,在您的设备日志和 JSON 格式中,您似乎应该遵循此处显示的示例:https://developer.apple.com/documentation/safariservices/supporting_associated_domains
在您的日志中,它可能会显示来自其他同样具有过时 API 格式的应用程序的日志。然而,这应该不是什么大问题。
{
"applinks": {
"details": [
{
"appIDs": [ "ABCDE12345.com.example.app", "ABCDE12345.com.example.app2" ],
"components": [
{
"#": "no_universal_links",
"exclude": true,
"comment": "Matches any URL whose fragment equals no_universal_links and instructs the system not to open it as a universal link"
},
{
"/": "/buy/*",
"comment": "Matches any URL whose path starts with /buy/"
},
{
"/": "/help/website/*",
"exclude": true,
"comment": "Matches any URL whose path starts with /help/website/ and instructs the system not to open it as a universal link"
},
{
"/": "/help/*",
"?": { "articleNumber": "????" },
"comment": "Matches any URL whose path starts with /help/ and which has a query item with name 'articleNumber' and a value of exactly 4 characters"
}
]
}
]
},
"webcredentials": {
"apps": [ "ABCDE12345.com.example.app" ]
},
"appclips": {
"apps": ["ABCED12345.com.example.MyApp.Clip"]
}
}
其次按照 Apple 的故障排除步骤和您的问题我猜您的问题可能是第 7 步
您的应用从以下其中一项返回 false
UIApplicationDelegate 协议方法:
应用程序(:continueUserActivity:restorationHandler:),
应用程序(:willFinishLaunchingWithOptions:),
应用程序(_:didFInishLaunchingWithOptions :).
这可能会发生,如果你
解析了传递给这些方法的 URL,然后你实现了
确定您的应用程序不能使用此 URL.
的逻辑
您还没有发布您如何处理 URL。您需要按照其他答案中的建议实施 UIUserActivityRestoring
方法才能使其正常工作。这是一个 SwiftUI 版本
ContentView()
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in
print("Continue activity \(userActivity)")
guard let url = userActivity.webpageURL else {
return
}
print("User wants to open URL: \(url)")
// TODO same handling as done in onOpenURL()
}
同时添加
.onOpenURL { url in
print("URL OPENED")
print(url) // parse the url to get someAction to determine what the app needs do
if url.relativeString == "example://success" {
}
}
https://developer.apple.com/library/archive/qa/qa1916/_index.html
我试图在访问 www.example.com/success as well as show a banner when visiting the homepage www.example.com.
时将用户重定向到已安装的应用程序在我目前的植入中,url 不会重定向和打开应用程序,网站也不会显示横幅。
我正在按照此处找到的文档进行操作 https://developer.apple.com/documentation/safariservices/supporting_associated_domains
我的网站是一个简单的 create-react-app
,主页由 Firebase 托管。
我做了以下事情:
- 将关联域添加到签名和功能 - applinks:website.com/success
- 添加
apple-app-site-association
个文件到/public/ - 修改firebase.json文件
- Link 到 index.html 中的文件
我用什么来验证:
https://branch.io/resources/aasa-validator/
https://search.developer.apple.com/appsearch-validation-tool
通过添加www.example.com/success link 到注释并打开进行测试,它总是在safari 中打开。我也尝试过重新安装应用程序并重新启动 phone.
Apple API 验证
我已将具有关联域的新应用程序版本上传到商店
Branch.io
{
"applinks": {
"apps": [],
"details": []
}
}
访问时www.example.com/apple-app-site-association
{ "activitycontinuation": { "apps": [ "team.com.example.com" ] }, "applinks": { "apps": [], "details": [ { "appID": "team.com.example.com", "paths": [ "/", "/", "/success", "/success/",] }, "webcredentials": { "apps": [ "team.com.example.com" ] } }
apple-app-site-association
{
"activitycontinuation": {
"apps": [
"team.com.example.com"
]
},
"applinks": {
"apps": [],
"details": [
{
"appID": "team.com.example.com",
"paths": [
"/",
"/*",
"/success",
"/success/*",
]
},
]
},
"webcredentials": {
"apps": [
"team.com.example.com"
]
}
}
Index.html
<link rel="apple-app-site-association file" href="%PUBLIC_URL%/apple-app-site-association">
<link rel="apple-app-site-association file" href="/apple-app-site-association">
<meta name="App" content="app-id=XXX, app-argument=https://apps.apple.com/US/app/APP/idXXX, affiliate- data=optionalAffiliateData">
Firebase.json
{
"hosting": {
"public": "public",
"headers": [
{
"source": "/apple-app-site-association",
"headers": [
{
"key": "Content-Type",
"value": "application/json"
}
]
}
],
"appAssociation": "NONE"
}
}
设备控制台
安装应用程序时,我在 Xcode 中监视设备控制台,查看 swdc
进程日志以查找与关联域或请求相关的任何内容。这是我找到的一些;
Error getting enterprise-managed associated domains data. If this device is not enterprise-managed, this is normal: Error Domain=SWCErrorDomain Code=1701 "Failed to get associated domain data from ManagedConfiguration framework." UserInfo={NSDebugDescription=Failed to get associated domain data from ManagedConfiguration framework., Line=298, Function=}
Entry { s = applinks, a = , d = au….ub….com, ua = unspecified, sa = approved } needs its JSON updated because the app PI changed
https://developer.apple.com/library/archive/qa/qa1916/_index.html
apple-app-site-association
中需要一个appID:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "XXXXXXXXXX.com.example.UniveralLinks",
"paths": ["*"]
}
]
}
}
applinks 标签确定哪些应用程序与网站相关联。将 apps 值保留为空数组。在 details 标签内是一个字典数组,用于 linking appIDs 和 URL 路径。为简单起见,您使用 * 通配符将此网站的所有 link 与 UniversalLinks 应用相关联。您可以将路径值限制为特定文件夹或文件名。 appID 由您的团队 ID 和应用程序的 bundle ID 组成,但您需要为自己的帐户使用标识符。 当您创建 Apple 开发者帐户时,Apple 会为您分配一个团队 ID。您可以在 Apple 开发人员中心找到它。登录网站,单击会员资格,然后在会员信息部分查找团队 ID。
现在您有了 apple-app-site-association,必须将它上传到 Web 服务器。
您 必须对网站具有“写入权限” 才能执行此操作。确保您正确设置了 apple-app-site-association
文件(在您的网络服务器上的根目录或 .well-known/
中,并且没有重定向)。
您还必须向 iOS 应用程序添加适用于通用 linking 的适当权利。 如果您使用 Xcode:
- Select 项目。
- Select目标。
- Select 功能选项卡。
- 滚动到并打开关联域。
然后您可以添加例如applinks:www.mywebsite.in
在“功能 -> 关联域”下。
或者在您的权利文件中,您可以添加如下内容:
<key>com.apple.developer.associated-domains</key>
<array>
...
<string>applinks:www.mywebsite.in</string>
...
</array>
处理通用链接: 现在应用程序和网站正式相互了解,应用程序需要的只是在调用时处理 link 的代码。
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?
) -> Void) -> Bool {
// 1
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL,
let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return false
}
// 2 // dig out component for deepLinking reference.
if let component = ItemHandler.sharedInstance.items
.filter({ [=12=].path == components.path}).first {
//handle navigation to page indicated by component
return true
}
// 3
if let webpageUrl = URL(string: "http://universal-links-final.example.com") {
application.open(webpageUrl)
return false
}
return false
}
每当用户点击与应用程序相关的通用 link 时,iOS 就会调用此方法。以下是每个步骤的作用: 首先,您验证传入的 userActivity 是否具有预期的特征。最终,您想要获取 activity 的路径组件。否则,您 return false 表示该应用无法处理 activity。 使用该路径,您可以查找与其匹配的已知视图控制器。如果找到一个,则为它显示视图控制器并且 return 为真。 如果找不到与路径匹配的视图控制器,则指示应用程序打开 URL,它将使用默认的系统应用程序代替——很可能是 Safari。你在这里也 return false 表示应用程序无法处理这个用户 activity.
首先,在您的设备日志和 JSON 格式中,您似乎应该遵循此处显示的示例:https://developer.apple.com/documentation/safariservices/supporting_associated_domains
在您的日志中,它可能会显示来自其他同样具有过时 API 格式的应用程序的日志。然而,这应该不是什么大问题。
{
"applinks": {
"details": [
{
"appIDs": [ "ABCDE12345.com.example.app", "ABCDE12345.com.example.app2" ],
"components": [
{
"#": "no_universal_links",
"exclude": true,
"comment": "Matches any URL whose fragment equals no_universal_links and instructs the system not to open it as a universal link"
},
{
"/": "/buy/*",
"comment": "Matches any URL whose path starts with /buy/"
},
{
"/": "/help/website/*",
"exclude": true,
"comment": "Matches any URL whose path starts with /help/website/ and instructs the system not to open it as a universal link"
},
{
"/": "/help/*",
"?": { "articleNumber": "????" },
"comment": "Matches any URL whose path starts with /help/ and which has a query item with name 'articleNumber' and a value of exactly 4 characters"
}
]
}
]
},
"webcredentials": {
"apps": [ "ABCDE12345.com.example.app" ]
},
"appclips": {
"apps": ["ABCED12345.com.example.MyApp.Clip"]
}
}
其次按照 Apple 的故障排除步骤和您的问题我猜您的问题可能是第 7 步
您的应用从以下其中一项返回 false UIApplicationDelegate 协议方法: 应用程序(:continueUserActivity:restorationHandler:), 应用程序(:willFinishLaunchingWithOptions:), 应用程序(_:didFInishLaunchingWithOptions :).
这可能会发生,如果你 解析了传递给这些方法的 URL,然后你实现了 确定您的应用程序不能使用此 URL.
的逻辑
您还没有发布您如何处理 URL。您需要按照其他答案中的建议实施 UIUserActivityRestoring
方法才能使其正常工作。这是一个 SwiftUI 版本
ContentView()
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in
print("Continue activity \(userActivity)")
guard let url = userActivity.webpageURL else {
return
}
print("User wants to open URL: \(url)")
// TODO same handling as done in onOpenURL()
}
同时添加
.onOpenURL { url in
print("URL OPENED")
print(url) // parse the url to get someAction to determine what the app needs do
if url.relativeString == "example://success" {
}
}
https://developer.apple.com/library/archive/qa/qa1916/_index.html