关联
Linking 为你提供了一个通用接口,用于与进入应用和从应用发出的链接交互。
每个链接(URL)都有一个 URL Scheme,一些网站会以 https:// 或 http:// 作为前缀,而 http 就是 URL Scheme。我们简称它为 scheme。
除了 https,你可能也熟悉 mailto scheme。当你打开一个使用 mailto scheme 的链接时,你的操作系统会打开已安装的邮件应用。同样,也有用于拨打电话和发送短信的 scheme。更多内容请阅读下面的 内置 URL schemes。
和使用 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 上,你需要将 LinkingIOS 文件夹添加到你的头文件搜索路径中,如 这里 的第 3 步所述。如果你还希望在应用运行期间监听传入的应用链接,你需要在你的 *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];
}
如果你的应用使用了 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 事件类型并提供处理函数,向 Linking 变化添加一个处理函数。
canOpenURL()
static canOpenURL(url: string): Promise<boolean>;
确定已安装的应用是否能够处理给定的 URL。
该方法返回一个 Promise 对象。当确定给定的 URL 是否可被处理后,promise 会被 resolve,第一个参数表示是否可以打开。
如果无法检查 URL 是否可打开,或者在目标为 Android 11(SDK 30)时你没有在 AndroidManifest.xml 中指定相关的 intent queries,Android 上的 Promise 将被 reject。同样,在 iOS 上,如果你没有在 Info.plist 中的 LSApplicationQueriesSchemes 键内添加具体的 scheme,promise 也会被 reject(见下文)。
参数:
| 名称 | 类型 | 描述 |
|---|---|---|
| url Required | 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 中为你想要处理的 schemes 指定 intents。常见 intents 的列表可在 此处 找到。
例如,要处理 https schemes,需要将以下内容添加到你的 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 Required | 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 Required | string |
| extras | Array<{key: string, value: string | number | boolean}> |