iOS 通用链接

了解如何配置 iOS 通用链接以从标准 Web URL 打开你的 Expo 应用。


要为你的应用配置 iOS 通用链接,你需要设置双向关联以验证你的网站和原生应用。

¥To configure iOS Universal Links for your app, you need to set up the two-way association to verify your website and native app.

Watch: Set up iOS Universal Links with Expo Router
Watch: Set up iOS Universal Links with Expo Router

在应用/扩展之间共享数据库(iOS)

¥Set up two-way association

要设置网站和 iOS 应用之间的双向关联,你需要执行以下步骤:

¥To setup two-way association between the website and app for iOS, you need to perform the following steps:

  • 网站验证:这需要在 /.well-known 目录中创建一个 apple-app-site-association (AASA) 文件并将其托管在目标网站上。此文件用于验证从给定链接打开的应用是否是正确的应用。

    ¥Website verification: This requires creating a apple-app-site-association (AASA) file inside the /.well-known directory and hosting it on the target website. This file is used to verify that the app opened from a given link is the correct app.

  • 原生应用验证:这需要某种形式的引用目标网站域 (URL) 的代码签名。

    ¥Native app verification: This requires some form of code signing that references the target website domain (URL).

创建 AASA 文件

¥Create AASA file

在 /.well-known 目录内为网站验证创建 apple-app-site-association 文件。此文件指定你的 Apple 开发者团队 ID、打包包标识符以及重定向到原生应用的支持路径列表。

¥Create an apple-app-site-association file for the website verification inside the /.well-known directory. This file specifies your Apple Developer Team ID, bundle identifier, and a list of supported paths to redirect to the native app.

你可以在项目中运行实验性的 CLI 命令 npx setup-safari,以自动将包标识符注册到你的 Apple 账户,为 ID 分配权利,并在商店中创建 iTunes 应用条目。将打印本地设置,你可以跳过以下大部分内容。这是在 iOS 上开始使用通用链接的最简单方法。

如果你使用 Expo Router 构建你的网站(或任何其他现代 React 框架,如 Remix、Next.js 等),请在 public/.well-known/apple-app-site-association 创建 AASA 文件。对于旧版 Expo webpack 项目,请在 web/.well-known/apple-app-site-association 创建文件。

¥If you're using Expo Router to build your website (or any other modern React framework such as Remix, Next.js, and so on), create the AASA file at public/.well-known/apple-app-site-association. For legacy Expo webpack projects, create the file at web/.well-known/apple-app-site-association.

public/.well-known/apple-app-site-association
{
  // This section enables Universal Links
  "applinks": {
    "apps": [],
    "details": [
      {
        // Syntax: "<APPLE_TEAM_ID>.<BUNDLE_ID>"
        "appID": "QQ57RJ5UTD.com.example.myapp",
        // All paths that should support redirecting.
        "paths": ["/records/*"]
      }
    ]
  },
  // This section enables Apple Handoff
  "activitycontinuation": {
    "apps": ["<APPLE_TEAM_ID>.<BUNDLE_ID>"]
  },
  // This section enable Shared Web Credentials
  "webcredentials": {
    "apps": ["<APPLE_TEAM_ID>.<BUNDLE_ID>"]
  }
}

在上面的例子中:

¥In the above example:

  • 任何指向 https://www.myapp.io/records/* 的链接(记录 ID 使用通配符匹配)都应由 iOS 设备上具有匹配包标识符的应用直接打开。它是 苹果团队 ID 和包标识符的组合。

    ¥Any links to https://www.myapp.io/records/* (with wildcard matching for the record ID) should be opened directly by the app with a matching bundle identifier on an iOS device. It is a combination of the Apple Team ID and the bundle identifier.

  • * 通配符与域或路径分隔符(句点和斜杠)不匹配。

    ¥The * wildcard does not match domain or path separators (periods and slashes).

  • activitycontinuationwebcredentials 对象是可选的,但建议使用。

    ¥The activitycontinuation and webcredentials objects are optional, but recommended.

有关 AASA 格式的更多详细信息,请参阅 苹果的文档。Branch 提供了 AASA 验证器,它可以帮助你确认你的 AASA 已正确部署并且具有有效的格式。

¥See Apple's documentation for further details on the format of the AASA. Branch provides an AASA validator which can help you confirm that your AASA is correctly deployed and has a valid format.

Suspense

截至 iOS 13 的 details 格式是支持。它允许你指定:

¥The details format is supported as of iOS 13. It allows you to specify:

  • appIDs 代替 appID:使将多个应用与相同配置关联起来更容易

    ¥appIDs instead of appID: Makes it easier to associate multiple apps with the same configuration

  • components 数组:允许你指定片段、排除特定路径和添加注释

    ¥An array of components: Allows you to specify fragments, exclude specific paths, and add comments

An example AASA JSON from Apple's documentation
public/.well-known/apple-app-site-association
{
  "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"
          }
        ]
      }
    ]
  }
}

要支持所有 iOS 版本,你可以在 details 密钥中提供上述两种格式,但我们建议首先放置更新的 iOS 版本的配置。

¥To support all iOS versions, you can provide both the above formats in your details key, but we recommend placing the configuration for more recent iOS versions first.

托管 AASA 文件

¥Host AASA file

使用你域中的 Web 服务器托管 apple-app-site-association 文件。此文件必须通过 HTTPS 连接提供。验证你的浏览器是否可以访问此文件。

¥Host the apple-app-site-association file using a web server with your domain. This file must be served over an HTTPS connection. Verify that your browser can access this file.

设置 AASA 文件后,将网站部署到支持 HTTPS(大多数现代 Web 主机)的服务器。

¥After you have setup the AASA file, deploy your website to a server that supports HTTPS (most modern web hosts).

原生应用配置

¥Native app configuration

部署你的 apple-app-site-association (AASA) 文件后,通过将 ios.associatedDomains 添加到你的 应用配置 来配置你的应用以使用你的关联域。确保遵循 苹果指定的格式,并且不要在你的 URL 中包含协议(https)。这是一个常见错误,会导致通用链接不起作用。

¥After deploying your apple-app-site-association (AASA) file, configure your app to use your associated domain by adding ios.associatedDomains to your app config. Make sure to follow Apple's specified format and not include the protocol (https) in your URL. This is a common mistake that will result in the universal links not working.

例如,如果关联网站是 https://expo.dev/,则 applinks 是:

¥For example, if an associated website is https://expo.dev/, the applinks is:

app.json
{
  "expo": {
    "ios": {
      "associatedDomains": ["applinks:expo.dev"]
    }
  }
}

使用 EAS 构建 构建你的 iOS 应用,以确保自动向 Apple 注册授权。

¥Build your iOS app with EAS Build which ensures that the entitlement is registered with Apple automatically.

Manual native configuration

如果你没有使用 EAS 或 持续的原生生成 (npx expo prebuild),则必须将关联域功能添加到你的打包标识符中。

¥If you're not using EAS or Continuous Native Generation (npx expo prebuild), you have to manually configure the Associated Domains capability for your bundle identifier.

如果你通过 苹果开发者控制台 启用,请确保在你的 ios/[app]/[app].entitlements 文件中添加以下权利:

¥If you enable through the Apple Developer Console, then make sure to add the following entitlements in your ios/[app]/[app].entitlements file:

<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:expo.dev</string>
</array>

原生应用验证

¥Native app verification

在你的 iOS 设备上安装应用以触发验证过程。移动设备上指向你网站的链接应该会打开你的应用。如果没有,请重新检查前面的步骤以确保你的 AASA 有效、AASA 中指定的路径,并且你已在 苹果开发者控制台 中正确配置了你的 App ID。

¥Install the app on your iOS device to trigger the verification process. A link to your website on your mobile device should open your app. If it doesn't, re-check the previous steps to ensure that your AASA is valid, the path specified in the AASA, and you have correctly configured your App ID in the Apple Developer Console.

打开应用后,请参阅 处理进入你应用的链接 以获取有关如何处理入站链接并向用户显示他们请求的内容的更多信息。

¥Once you have your app opened, see Handle links into your app for more information on how to handle inbound links and show the user the content they requested.

当你的应用首次安装或从 App Store 安装更新时,iOS 会下载你的 AASA。此后,操作系统不会频繁刷新。如果你想更改生产应用的 AASA 中的路径,则需要通过 App Store 发布完整更新,以便所有用户的应用重新获取你的 AASA 并识别新路径。

¥iOS downloads your AASA when your app is first installed or when updates are installed from the App Store. The operating system does not refresh frequently after that. If you want to change the paths in your AASA for a production app, you will need to issue a full update via the App Store so that all of your users' apps re-fetch your AASA and recognize the new paths.

苹果智能横幅

¥Apple Smart Banner

如果用户没有安装你的应用,他们将被定向到该网站。你可以使用 苹果智能横幅 在页面顶部显示横幅,提示用户安装应用。仅当用户使用移动设备且未安装应用时,横幅才会显示。

¥If a user doesn't have your app installed, they'll be directed to the website. You can use the Apple Smart Banner to show a banner at the top of the page that prompts the user to install the app. The banner will only show up if the user is on a mobile device and doesn't have the app installed.

要启用横幅,请将以下元标记添加到你网站的 <head>,并将 <ITUNES_ID> 替换为你应用的 iTunes ID:

¥To enable the banner, add the following meta tag to the <head> of your website, replacing <ITUNES_ID> with your app's iTunes ID:

<meta name="apple-itunes-app" content="app-id=<ITUNES_ID>" />

如果你在设置横幅时遇到问题,请运行以下命令来自动为你的项目生成元标记:

¥If you're having trouble setting up the banner, run the following command to automatically generate the meta tag for your project:

Terminal
npx setup-safari

将元标记添加到你的静态渲染的网站

¥Add the meta tag to your statically rendered website

如果你正在构建 使用 Expo Router 静态渲染网站,则将 HTML 标记添加到 app/+html.js 文件 中的 <head> 组件。

¥If you're building a statically rendered website with Expo Router, then add the HTML tag to the <head> component in your app/+html.js file.

app/+html.tsx
import { type PropsWithChildren } from 'react';

export default function Root({ children }: PropsWithChildren) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
        <meta name="apple-itunes-app" content="app-id=<ITUNES_ID>" />
        {/* Other head elements... */}
      </head>
      <body>{children}</body>
    </html>
  );
}

调试

¥Debugging

Expo CLI 使你无需部署网站即可测试 iOS 通用链接。利用 --tunnel 功能,你可以将开发服务器转发到公开可用的 HTTPS URL。

¥Expo CLI enables you to test iOS Universal Links without deploying a website. Utilizing the --tunnel functionality, you can forward your dev server to a publicly available HTTPS URL.

1

设置环境变量 EXPO_TUNNEL_SUBDOMAIN=my-custom-domain,其中 my-custom-domain 是你在开发过程中使用的唯一字符串。这可确保你的隧道 URL 在开发服务器重启时保持一致。

¥Set the environment variable EXPO_TUNNEL_SUBDOMAIN=my-custom-domain where my-custom-domain is a unique string that you use during development. This ensures that your tunnel URL is consistent across dev server restarts.

2

associatedDomains 作为 如上所述 添加到你的应用配置中。用 Ngrok URL 替换域值:my-custom-domain.ngrok.io

¥Add associatedDomains to your app config as described above. Replace the domain value with a Ngrok URL: my-custom-domain.ngrok.io.

3

使用 --tunnel 标志启动你的开发服务器:

¥Start your dev server with the --tunnel flag:

Terminal
npx expo start --tunnel

4

在你的设备上编译开发版本:

¥Compile the development build on your device:

Terminal
npx expo run:ios

你现在可以在设备的 Web 浏览器中键入自定义域链接来打开你的应用。

¥You can now type your custom domain link in your device's web browser to open your app.

故障排除

¥Troubleshooting

以下是一些在实现 iOS 通用链接时帮助你排除故障的常见提示:

¥Here are some common tips to help you troubleshoot when implementing iOS Universal Links:

  • 阅读 Apple 关于 调试通用链接 的官方文档

    ¥Read Apple's official documentation on debugging universal links

  • 使用 验证器工具.conf 确保你的 Apple 应用站点关联文件有效。

    ¥Ensure your apple app site association file is valid by using a validator tool.

  • 未压缩的 apple-app-site-association 文件不能是 大于 128kb

    ¥The uncompressed apple-app-site-association file cannot be larger than 128kb.

  • 确保你的网站通过 HTTPS 提供服务。

    ¥Ensure your website is served over HTTPS.

  • 如果你更新 Web 文件,请重建原生应用以触发供应商端(Apple)的服务器更新。

    ¥If you update your web files, rebuild the native app to trigger a server update on the vendor side (Apple).