如何设置关联域/通用链接

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 托管。

我做了以下事情:

  1. 将关联域添加到签名和功能 - applinks:website.com/success
  2. 添加apple-app-site-association个文件到/public/
  3. 修改firebase.json文件
  4. Link 到 index.html
  5. 中的文件

我用什么来验证:

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:

  1. Select 项目。
  2. Select目标。
  3. Select 功能选项卡。
  4. 滚动到并打开关联域。

然后您可以添加例如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