苹果接力
编辑
了解如何通过 Expo Router 和苹果接力在 Apple 设备之间无缝继续应用导航。
苹果接力是一个功能,使用户能够在另一台设备上继续浏览您的应用或网站。Expo Router 自动化了此功能的所有运行时路由。但是,一次性配置必须手动设置。
在 Expo Router 中,底层 iOS API(NSUserActivity)需要一个 webpageUrl,操作系统建议将其作为切换到您的应用程序的当前 URL。expo-router/head 组件有一个可选的原生模块,可以自动将 webpageUrl 设置为 Expo Router 中当前聚焦的路由。
Platform Compatibility
| Android Device | Android Emulator | iOS Device | iOS Simulator | Web |
|---|---|---|---|---|
设置
以下限制和考虑事项非常重要:
- 接力仅限苹果。
- 接力无法在 Expo Go 应用中使用,因为它需要构建时配置。
- 接力要求配置 通用链接,至少在 iOS 上,并包含
activitycontinuation对象。 - 接力要求在您希望支持的每个页面上使用
expo-router/head组件,或者在根布局中以便所有页面都可以连续。
要确保 public/.well-known/apple-app-site-association 文件配置正确,必须包含 activitycontinuation 键,并具有包含您的应用程序的捆绑 ID 和团队 ID 格式为 <APPLE_TEAM_ID>.<IOS_BUNDLE_ID> 的 apps 数组。例如,QQ57RJ5UTD.app.expo.acme,其中 QQ57RJ5UTD 是团队 ID,app.expo.acme 是捆绑标识符。
{ "applinks": { "details": [ { "appIDs": ["<APPLE_TEAM_ID>.<IOS_BUNDLE_ID>"], "components": [ { "/": "*", "comment": "Matches all routes" } ] } ] }, "activitycontinuation": { "apps": ["<APPLE_TEAM_ID>.<IOS_BUNDLE_ID>"] }, "webcredentials": { "apps": ["<APPLE_TEAM_ID>.<IOS_BUNDLE_ID>"] } }
webcredentials对象是可选的,但推荐使用。
您可以使用以下命令根据您的 app config 生成 apple-app-site-association 文件:
- npx setup-safari请参阅 测试深层链接 指南以测试开发中的接力。
Expo Head 设置
确保您在 app.config.tsx 文件中使用 expo-router 配置插件设置接力源。这是用户切换到您的应用程序时将用于 webpageUrl 的 URL。
// 确保将此更改为独特的项目。 process.env.EXPO_TUNNEL_SUBDOMAIN = 'bacon-router-sandbox'; const ngrokUrl = `${process.env.EXPO_TUNNEL_SUBDOMAIN}.ngrok.io`; /** @type {import('expo/config').ExpoConfig} */ module.exports = { // ... ios: { associatedDomains: [ `applinks:${ngrokUrl}`, `activitycontinuation:${ngrokUrl}`, `webcredentials:${ngrokUrl}`, // 在此处添加其他生产 URL。 // `applinks:example.com`, // `activitycontinuation:example.com`, // `webcredentials:example.com`, ], }, plugins: [ [ 'expo-router', { // 注意:在 "headOrigin" 中,URL 必须以 "https://" 开头 headOrigin: process.env.NODE_ENV === 'development' ? `https://${ngrokUrl}` : 'https://my-website-example.com', }, ], ], };
测试接力到原生时,请不要使用仅限开发的
?mode=developer后缀。
配置应用程序配置后,使用以下命令重新生成您的原生项目:
- npx expo prebuild -p ios在开发过程中,您必须在 安装应用程序到您的设备之前 启动网站。这是因为当您安装应用程序时,操作系统将触发苹果的服务器以对您的网站进行 ping 测试,以获取 .well-known/apple-app-site-association 文件。如果网站未运行,操作系统将无法找到该文件,接力将无法正常工作。如果发生这种情况,请使用 npx expo run:ios -d 重新构建原生应用程序。
使用
在您希望支持接力的任何路由中,使用 expo-router/head 中的 Head 组件:
import Head from 'expo-router/head'; import { Text } from 'react-native'; export default function App() { return ( <> <Head> <meta property="expo:handoff" content="true" /> </Head> <Text>Hello World</Text> </> ); }
元标记
expo-router/head 组件支持以下元标记:
| 元标记 | 描述 |
|---|---|
expo:handoff | 设置为 true 以启用当前路由的接力。默认值为 false。(仅限 iOS) |
og:title 和 <title> | 设置 NSUserActivity 的标题,这在接力中未使用。 |
og:description | 设置 NSUserActivity 的描述,这在接力中未使用。 |
og:url | 设置用户切换到您的应用时应打开的 URL。默认值为应用内当前 URL,在 expo-router 配置插件中为 headOrigin 属性,作为 baseURL。传递相对路径将把 headOrigin 附加到该路径。 |
您可能希望在平台之间切换值,对于此您可以使用 Platform.select:
import Head from 'expo-router/head'; export default function App() { return ( <Head> <meta property="og:url" content={Platform.select({ web: 'https://expo.dev', default: null })} /> </Head> ); }
调试
确保您的苹果设备已 启用接力。您可以通过以下步骤测试,但用 Safari 代替您的应用程序。
- 在您的设备上打开原生应用程序。
- 导航到应用程序中支持接力的路由,该路由正在呈现 Expo Router 的
<Head />元素。 - 切换到您的 Mac,并在 Dock 中点击应用程序的接力图标。
- 切换到您的 iPhone 或 iPad,打开应用程序切换器,并点击屏幕底部的应用程序横幅。
如果您在 iPhone 的应用程序切换器中只看到 Safari 图标,则表示接力无法工作。
故障排除
您可以使用验证器测试 Apple App Site Association 文件 (public/.well-known/apple-app-site-association),例如 AASA Validator。
如果您遇到问题,最好的办法是启用应用程序中最激进的接力设置。这可确保任何可能的路由都是可链接的。您可以通过确保 public/.well-known/apple-app-site-association 文件与所有路由匹配来做到这一点:
{ "applinks": { "details": [ { "appIDs": ["<APPLE_TEAM_ID>.<IOS_BUNDLE_ID>"], "components": [ { "/": "*", "comment": "Matches all routes" } ] } ] } }
在应用程序中,确保您无法有条件地渲染 <Head /> 元素(例如,在 if/else 块中),它必须在您希望支持接力的每个页面上呈现。我们建议将其添加到 根布局 组件中,以确保在调试时每个路由都是可链接的。
确保您可以访问 Ngrok URL(例如,通过浏览器),在将应用程序安装到您的设备之前。如果您无法访问该 URL,操作系统将无法找到该文件,接力将无法正常工作。
npx expo run:ios 和 Xcode 都会在设置关联域时对您的应用进行代码签名,这对于接力和通用链接的正常工作是必需的。
接力在您的 Mac 和 iPhone/iPad 之间在 Expo Go 应用中不受支持。您必须构建并安装应用程序到您的设备。
如果您在 iPhone 的应用程序切换器中看到 Safari 图标,则意味着接力无法正常工作。
- 确保在测试接力到原生时您没有使用
?mode=developer后缀。 - 还要确保您没有使用本地开发服务器 URL。例如,
http://localhost:8081,因为这不能用作有效的应用程序网站关联链接,请在浏览器中打开正在运行的 Ngrok URL 以进行测试。 - 确保您的 public/.well-known/apple-app-site-association 文件包含
activitycontinuation字段。 - 我们观察到在 iOS 16.3.1 和 macOS 13.0(Ventura)中,以
app.和io.开头的捆绑标识符有时不会触发原生应用在 iOS 任务切换器中显示。将com.作为捆绑标识符的第一个部分使用。
您的 public/.well-known/apple-app-site-association 必须从安全 URL(HTTPS)提供。如果您使用开发通道,必须使用 EXPO_TUNNEL_SUBDOMAIN 环境变量来配置开发通道的子域。此通道是开发中测试所必需的,因为您需要使用 SSL 来使用通用链接,Expo CLI 通过运行 npx expo start --tunnel 提供对此的内置支持。
检查您的 ios/project/project.entitlements 文件,查找 com.apple.developer.associated-domains 键。这应包含与您的 Web 服务器/网站相同的域。URL 不能包含协议(https://)或附加的路径名、查询参数或片段。
仍然困惑
这是一个重要但非常难以设置的功能。Expo Router 自动化了许多移动部分,Expo CLI 自动化了许多配置和托管。但是,硬件设置仍然可能配置错误。
如果一切都失败了,您可以尝试按照 Apple Docs 中的步骤进行调试。注意:
- “将用户活动表示为
NSUserActivity的实例。” 是由 Expo Head 原生模块执行的。 - “在用户在应用程序中执行操作时更新活动实例。” 是通过将
<Head />组件与元标签<meta property="expo:handoff" content="true" />一起挂载/呈现执行的。 - “在您的应用中的其他设备上接收来自接力的活动。” 是由 Expo Head 原生模块中的 App Delegate Subscriber 执行的。它用于在您传递到原生应用程序时将您重定向到正确的路由。
已知问题
从 Web 到原生的接力不支持客户端路由。这意味着在应用程序切换器中呈现的 URL 将是您点击链接或重新加载页面时所处页面的 URL。这是 Web 平台的限制,而不是 Expo Router 可以解决的问题。