链接
Linking 为你提供了一个通用接口,用于与传入和传出的应用链接进行交互。
每个链接(URL)都有一个 URL Scheme,一些网站会以前缀 https:// 或 http:// 开头,其中 http 就是 URL Scheme。我们简称它为 scheme。
除了 https 之外,你可能也熟悉 mailto scheme。当你打开一个带有 mailto scheme 的链接时,你的操作系统会打开已安装的邮件应用。同样地,也有用于拨打电话和发送 SMS 的 scheme。更多内容请阅读下面的内置 URL scheme。
和使用 mailto scheme 类似,也可以通过自定义 url scheme 来链接到其他应用。例如,当你收到来自 Slack 的 Magic Link 邮件时,Launch Slack 按钮是一个带有 href 的锚点标签,看起来大概像这样:slack://secret/magic-login/other-secret。和 Slack 一样,你可以告诉操作系统你想处理某个自定义 scheme。当 Slack 应用打开时,它会接收到用于打开它的 URL。这通常被称为深度链接。更多关于如何将深度链接引入你的应用的信息,请阅读相关内容。
自定义 URL scheme 并不是在移动端打开你的应用的唯一方式。例如,如果你想给某人发送一条链接,让其在移动端打开,使用自定义 URL scheme 并不理想,因为用户可能会在桌面端打开邮件,而在那里这个链接无法工作。相反,你应该使用标准的 https 链接,例如 https://www.myapp.io/records/1234546。在移动端,这些链接可以配置为打开你的应用。在 Android 上,这个功能叫做 Deep Links,而在 iOS 上,它被称为 Universal Links。
内置 URL Schemes
如前言所述,所有平台上都存在一些用于核心功能的 URL scheme。下面的列表并不完整,但涵盖了最常用的 scheme。
| Scheme | 描述 | iOS | Android |
|---|---|---|---|
mailto | 打开邮件应用,例如:mailto: hello@world.dev | ✅ | ✅ |
tel | 打开电话应用,例如:tel:+123456789 | ✅ | ✅ |
sms | 打开短信应用,例如:sms:+123456789 | ✅ | ✅ |
https / http | 打开网页浏览器应用,例如: https://expo.dev | ✅ | ✅ |
启用深度链接
如果你想在应用中启用深度链接,请阅读下面的指南:
- Android
- iOS
有关如何在 Android 上添加对深度链接支持的说明,请参阅 为应用内容启用深度链接 - 为你的深度链接添加 Intent Filters。
如果你希望在已有的 MainActivity 实例中接收 intent,可以在 AndroidManifest.xml 中将 MainActivity 的 launchMode 设置为 singleTask。更多信息请参阅 <activity> 文档。
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
注意: 在 iOS 上,你需要像这里第 3 步所述那样,将
LinkingIOS文件夹添加到 header search paths 中:这里。如果你还想在应用运行期间监听传入的应用链接,你需要将以下几行添加到你的*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];
}
如果你的应用使用了 Universal Links,你还需要添加以下代码:
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return RCTLinkingManager.application(app, open: url, options: options)
}
如果你的应用使用了 Universal Links,你还需要添加以下代码:
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) 来处理这些事件——它会用链接 URL 调用 callback({url})
2. 如果应用尚未打开,它会被启动,并且 url 会作为 initialURL 传入
你可以使用 Linking.getInitialURL() 来处理这些事件——它会返回一个 Promise,如果存在 URL,则解析为该 URL。
示例
打开链接和深度链接(Universal Links)
- TypeScript
- JavaScript
打开自定义设置
- TypeScript
- JavaScript
获取深度链接
- TypeScript
- JavaScript
发送 Intent(Android)
- TypeScript
- JavaScript
Reference
方法
addEventListener()
static addEventListener(
type: 'url',
handler: (event: {url: string}) => void,
): EmitterSubscription;
通过监听 url 事件类型并提供 handler,向 Linking 变更添加一个处理函数。
canOpenURL()
static canOpenURL(url: string): Promise<boolean>;
判断已安装的应用是否可以处理给定的 URL。
该方法返回一个 Promise 对象。当确定给定 URL 是否可处理后,promise 会被 resolve,且第一个参数表示是否可以打开。
如果在 Android 上无法检查该 URL 是否可打开,或者在面向 Android 11(SDK 30)时未在 AndroidManifest.xml 中指定相关的 intent queries,Promise 将会 reject。同样地,在 iOS 上,如果你没有在 Info.plist 的 LSApplicationQueriesSchemes 键中添加特定 scheme,promise 也会 reject(见下文)。
参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| url 必填 | string | 要打开的 URL。 |
对于 web 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中为你想处理的 scheme 指定 intents。常见 intents 列表可在这里找到。例如,要处理
httpsscheme,需要将以下内容添加到你的 manifest 中:<manifest ...><queries><intent><action android:name="android.intent.action.VIEW" /><data android:scheme="https"/></intent></queries></manifest>
getInitialURL()
static getInitialURL(): Promise<string | null>;
如果应用启动是由 app link 触发的,则返回链接 url;否则返回 null。
要在 Android 上支持深度链接,请参考 https://developer.android.com/training/app-indexing/deep-linking.html#handling-intents
当 Remote JS Debugging 处于活动状态时,
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 会被 resolve。如果用户取消打开对话框,或者没有为该 url 注册任何应用,promise 会被 reject。
参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| url 必填 | string | 要打开的 URL。 |
如果系统不知道如何打开指定的 URL,此方法将失败。如果你传入的是非 http(s) URL,最好先检查
canOpenURL()。
对于 web URL,协议(
"http://","https://")必须正确设置!
该方法在模拟器中的行为可能不同,例如 iOS 模拟器无法处理
"tel:"链接,因为无法访问拨号器应用。
sendIntent() Android
static sendIntent(
action: string,
extras?: Array<{key: string; value: string | number | boolean}>,
): Promise<void>;
使用 extras 启动一个 Android intent。
参数:
| 名称 | 类型 |
|---|---|
| action 必填 | string |
| extras | Array<{key: string, value: string | number | boolean}> |