链接
Linking 为你提供了一个通用接口,用于处理传入和传出的应用链接。
每个链接 (URL) 都有一个 URL Scheme,有些网站以 https:// 或 http:// 为前缀,这里的 http 就是 URL Scheme。我们简称为 scheme。
除了 https,你可能还熟悉 mailto scheme。当你打开一个带有 mailto scheme 的链接时,你的操作系统将打开已安装的邮件应用程序。同样,也有用于拨打电话和发送短信的 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 上,此功能称为 深度链接,而在 iOS 上,它被称为 通用链接。
内置 URL Scheme
如引言中所述,每个平台上都存在一些用于核心功能的 URL scheme。以下是一个非详尽的列表,但涵盖了最常用的 scheme。
| Scheme | 描述 | iOS | Android |
|---|---|---|---|
mailto | 打开邮件应用,例如:mailto: hello@world.dev | ✅ | ✅ |
tel | 打开电话应用,例如:tel:+123456789 | ✅ | ✅ |
sms | 打开短信应用,例如:sms:+123456789 | ✅ | ✅ |
https / http | 打开 Web 浏览器应用,例如:https://expo.dev | ✅ | ✅ |
启用深度链接
如果你想在应用中启用深度链接,请阅读以下指南:
- Android
- iOS
有关如何在 Android 上添加深度链接支持的说明,请参阅 为应用内容启用深度链接 - 为你的深度链接添加 Intent 过滤器。
如果你希望在现有的 MainActivity 实例中接收 intent,你可以在 AndroidManifest.xml 中将 MainActivity 的 launchMode 设置为 singleTask。有关更多信息,请参阅 <activity> 文档。
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
注意: 在 iOS 上,你需要按照第 3 步 此处 所述将
LinkingIOS文件夹添加到你的头文件搜索路径中。如果你还希望在应用执行期间监听传入的应用链接,你需要将以下行添加到你的*AppDelegate.m中:
- ObjectiveC
- Swift
// iOS 9.x 或更高版本
#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];
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return RCTLinkingManager.application(app, open: url, options: options)
}
如果你的应用使用的是 通用链接,你还需要添加以下代码:
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,如果有的话,该 Promise 会解析为 URL。
示例
打开链接和深度链接(通用链接)
- TypeScript
- JavaScript
打开自定义设置
- TypeScript
- JavaScript
获取深度链接
- TypeScript
- JavaScript
发送 Intents (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 会被 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 次。达到该限制后,后续调用始终 resolve 为
false。如果用户重新安装或升级应用,iOS 会重置限制。自 iOS 9 起,您的应用还需要在
Info.plist内提供LSApplicationQueriesSchemes键,否则canOpenURL()将始终 resolve 为false。
当目标为 Android 11 (SDK 30) 时,您必须在
AndroidManifest.xml中指定要处理的 scheme 的 intents。常见 intents 列表可在 此处 找到。例如,要处理
httpsschemes,需要将以下内容添加到您的 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/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 被 resolve。如果用户取消打开对话框或没有为该 url 注册的应用,则 promise 被 reject。
参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| url 必需 | string | 要打开的 URL。 |
如果系统不知道如何打开指定的 URL,此方法将失败。如果您传递的是非 http(s) URL,最好先检查
canOpenURL()。
对于 Web URL,必须相应地设置协议(
"http://","https://")!
此方法在模拟器中的行为可能不同,例如
"tel:"链接无法在 iOS 模拟器中处理,因为无法访问拨号器应用。
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}> |