Linking
Linking 提供了一个通用接口,用于处理传入和传出的应用链接。
每个链接(URL)都有一个 URL 方案,一些网站以 https:// 或 http:// 为前缀,其中 http 就是 URL 方案。我们将其简称为方案。
除了 https,您可能还熟悉 mailto 方案。当您打开一个带有 mailto 方案的链接时,您的操作系统将打开一个已安装的邮件应用程序。同样,还有用于拨打电话和发送短信的方案。请参阅下面的内置 URL 方案了解更多信息。
与使用 mailto 方案类似,可以通过使用自定义 URL 方案链接到其他应用程序。例如,当您从 Slack 收到一封魔术链接电子邮件时,“启动 Slack”按钮是一个带有 href 的锚点标签,其内容类似于:slack://secret/magic-login/other-secret。与 Slack 一样,您可以告知操作系统您希望处理自定义方案。当 Slack 应用打开时,它会收到用于打开它的 URL。这通常被称为深度链接。请参阅下面的如何获取深度链接到您的应用程序中。
自定义 URL 方案不是在移动设备上打开应用程序的唯一方法。例如,如果您想通过电子邮件将一个链接发送给某人,以便在移动设备上打开,那么使用自定义 URL 方案并不理想,因为用户可能在桌面设备上打开电子邮件,而链接将无法工作。相反,您应该使用标准的 https 链接,例如 https://www.myapp.io/records/1234546。在移动设备上,这些链接可以配置为打开您的应用程序。在 Android 上,此功能称为深度链接,而在 iOS 上,它被称为通用链接。
内置 URL 方案
正如引言中所述,存在一些每个平台上都存在的用于核心功能的 URL 方案。以下是一个不完全的列表,但涵盖了最常用的方案。
| 方案 | 描述 | iOS | Android |
|---|---|---|---|
mailto | 打开邮件应用程序,例如:mailto: hello@world.dev | ✅ | ✅ |
tel | 打开电话应用程序,例如:tel:+123456789 | ✅ | ✅ |
sms | 打开短信应用程序,例如:sms:+123456789 | ✅ | ✅ |
https / http | 打开网络浏览器应用程序,例如:https://expo.dev | ✅ | ✅ |
启用深度链接
如果您想在应用程序中启用深度链接,请阅读以下指南
- Android
- iOS
有关如何在 Android 上添加深度链接支持的说明,请参阅为应用程序内容启用深度链接 - 为深度链接添加 Intent 过滤器。
如果您希望在现有的 MainActivity 实例中接收 intent,您可以在 AndroidManifest.xml 中将 MainActivity 的 launchMode 设置为 singleTask。有关更多信息,请参阅<activity> 文档。
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
在 iOS 上,您需要将 LinkingIOS 文件夹添加到您的头文件搜索路径中,如此处的步骤 3 所述。如果您还想在应用程序执行期间监听传入的应用程序链接,您需要将以下行添加到您的 *AppDelegate.m
- ObjectiveC
- Swift
// iOS 9.x or newer
#import <React/RCTLinkingManager.h>
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}
如果您的应用程序使用通用链接,您还需要添加以下代码
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return RCTLinkingManager.application(app, open: url, options: options)
}
如果您的应用程序使用通用链接,您还需要添加以下代码
override func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
return RCTLinkingManager.application(
application,
continue: userActivity,
restorationHandler: restorationHandler
)
}
处理深度链接
有两种方法可以处理打开应用程序的 URL。
1. 如果应用程序已经打开,应用程序将被置于前台,并触发一个 Linking 'url' 事件
您可以使用 Linking.addEventListener('url', callback) 处理这些事件 - 它会调用 callback({url}) 并传入链接的 URL
2. 如果应用程序尚未打开,它将被打开,并且 URL 将作为 initialURL 传入
您可以使用 Linking.getInitialURL() 处理这些事件 - 它返回一个 Promise,如果存在 URL,则解析为该 URL。
示例
打开链接和深度链接(通用链接)
- TypeScript
- JavaScript
打开自定义设置
- TypeScript
- JavaScript
获取深度链接
- TypeScript
- JavaScript
发送 Intent (Android)
- TypeScript
- JavaScript
参考
方法
addEventListener()
static addEventListener(
type: 'url',
handler: (event: {url: string}) => void,
): EmitterSubscription;
通过监听 url 事件类型并提供处理程序来添加 Linking 更改的处理程序。
canOpenURL()
static canOpenURL(url: string): Promise<boolean>;
确定已安装的应用程序是否可以处理给定的 URL。
该方法返回一个 Promise 对象。当确定是否可以处理给定的 URL 时,Promise 将被解析,第一个参数表示是否可以打开。
在 Android 上,如果无法检查 URL 是否可以打开,或者在目标 Android 11 (SDK 30) 时,如果您未在 AndroidManifest.xml 中指定相关的 intent 查询,则 Promise 将被拒绝。类似地,在 iOS 上,如果您未在 Info.plist 中的 LSApplicationQueriesSchemes 键中添加特定方案(参见下文),Promise 将被拒绝。
参数
| 姓名 | 类型 | 描述 |
|---|---|---|
| 网址 必需 | 字符串 | 要打开的 URL。 |
对于网络 URL,协议("http://", "https://")必须相应设置!
此方法在 iOS 9+ 上存在限制。来自官方 Apple 文档
- 如果您的应用程序链接到早期版本的 iOS 但在 iOS 9.0 或更高版本上运行,您可以调用此方法最多 50 次。达到该限制后,后续调用始终解析为
false。如果用户重新安装或升级应用程序,iOS 会重置限制。 - 从 iOS 9 开始,您的应用程序还需要在
Info.plist中提供LSApplicationQueriesSchemes键,否则canOpenURL()将始终解析为false。
当目标为 Android 11 (SDK 30) 时,您必须在 AndroidManifest.xml 中指定要处理的方案的 intent。常见 intent 列表可在此处找到。
例如,要处理 https 方案,需要在您的 manifest 中添加以下内容
<manifest ...>
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https"/>
</intent>
</queries>
</manifest>
getInitialURL()
static getInitialURL(): Promise<string | null>;
如果应用程序启动是由应用程序链接触发的,它将提供链接 URL,否则它将提供 null。
要在 Android 上支持深度链接,请参阅https://developer.android.com.cn/training/app-indexing/deep-linking.html#handling-intents。
当远程 JS 调试处于活动状态时,getInitialURL 可能会返回 null。禁用调试器以确保其通过。
openSettings()
static openSettings(): Promise<void>;
打开“设置”应用程序并显示应用程序的自定义设置(如果有)。
openURL()
static openURL(url: string): Promise<any>;
尝试使用任何已安装的应用程序打开给定的 url。
您可以使用其他 URL,例如位置(例如 Android 上的“geo:37.484847,-122.148386”或 iOS 上的“https://maps.apple.com/?ll=37.484847,-122.148386”)、联系人或任何其他可以使用已安装应用程序打开的 URL。
该方法返回一个 Promise 对象。如果用户确认打开对话框或 URL 自动打开,则 Promise 将被解析。如果用户取消打开对话框或没有为 URL 注册的应用程序,则 Promise 将被拒绝。
参数
| 姓名 | 类型 | 描述 |
|---|---|---|
| 网址 必需 | 字符串 | 要打开的 URL。 |
如果系统不知道如何打开指定的 URL,此方法将失败。如果您传入非 http(s) URL,最好先检查 canOpenURL()。对于网络 URL,协议("http://","https://")必须相应设置!
此方法在模拟器中的行为可能有所不同,例如,在 iOS 模拟器中无法处理 "tel:" 链接,因为无法访问拨号器应用程序。
sendIntent() Android
static sendIntent(
action: string,
extras?: Array<{key: string; value: string | number | boolean}>,
): Promise<void>;
启动带有 extra 的 Android intent。
参数
| 姓名 | 类型 |
|---|---|
| action 必需 | 字符串 |
| extras | Array<{key: string, value: string | number | boolean}> |