Linking
Linking
提供了一个通用的接口来与传入和传出的 App 链接进行交互。
每个链接(URL)都有一个 URL Scheme,有些网站以 https://
或 http://
为前缀,而 http
就是 URL Scheme。我们简称它为 scheme。
除了 https
,你可能还熟悉 mailto
scheme。当您打开带有 mailto scheme 的链接时,操作系统将打开已安装的邮件应用程序。同样,也有打电话和发短信的 schemes。阅读下面关于内置 URL schemes 方案的更多信息。
与使用 mailto scheme 一样,可以通过使用自定义 url scheme 链接到其他应用程序。例如,当你收到一封来自 Slack 的 Magic Link 邮件时,Launch Slack 按钮是一个 anchor 标记,带有一个 href,看起来类似与 slack://secret/magic-login/other-secret
。就像 Slack 一样,你可以告诉操作系统你想要处理一个自定义 scheme。当 Slack 应用程序打开时,它会接收用于打开它的 URL。这通常被称为 Deep Links。阅读更多关于如何获得 Deep Links 到你的应用程序。
自定义 URL scheme 并不是在手机上打开应用程序的唯一方式。您不希望在电子邮件中的链接中使用自定义 URL scheme,因为这样链接在桌面上就会断开。相反,你想使用常规的 https
链接,如 https://www.myapp.io/records/1234546
。在移动设备上,你希望这个链接打开你的应用程序。Android 称之为 Deep Links (Universal Links - iOS)。
内置 URL Schemes
正如在介绍中提到的,每个平台上都存在一些核心功能的 URL schemes。以下是一个非详尽的列表,但涵盖了最常用的方案。
Scheme | 说明 | iOS | Android |
---|---|---|---|
mailto | 打开 mail app, 例如: mailto: support@expo.io | ✅ | ✅ |
tel | 打开 phone app, 例如: tel:+123456789 | ✅ | ✅ |
sms | 打开 SMS app, 例如: sms:+123456789 | ✅ | ✅ |
https / http | 打开 web browser app, 例如: https://expo.io | ✅ | ✅ |
基本用法
启用 Deep Links
如果你想在你的应用程序中启用 Deep Links,请遵循以下指南:
- Android
- iOS
要了解更多如何在 Android 上支持深度链接的说明,请参阅Enabling Deep Links for App Content - Add Intent Filters for Your Deep Links.
如果要在现有的 MainActivity 中监听传入的 intent,那么需要在AndroidManifest.xml
中将 MainActivity 的launchMode
设置为singleTask
。相关解释可参考<activity>
文档。
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
注意: 对于 iOS 来说,如果要在 App 启动后也监听传入的 App 链接,那么首先需要在项目中链接
RCTLinking
,具体步骤请参考手动链接这篇文档,然后需要在AppDelegate.m
中增加以下代码:
// 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];
}
// iOS 8.x 或更低版本
#import <React/RCTLinkingManager.h>
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [RCTLinkingManager application:application openURL:url
sourceApplication:sourceApplication annotation:annotation];
}
如果你的 app 用了 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];
}
处理 Deep Links
有两种方法来处理打开应用程序的 URL。
1. 如果应用程序已经打开,应用程序就会出现在前台,并触发一个链接 'url' 事件
你可以用 Linking.addEventListener('url', callback)
来处理这些事件——它使用链接的 URL 调用 callback({ url })
如果应用程序还没有打开,它就会被打开,并将 url 作为 initialURL 传入
你可以用 Linking.getInitialURL()
来处理这些事件——它会返回一个解析到 URL 的 Promise (如果有的话)。
示例
Open Links and Deep Links (Universal Links)
- TypeScript
- JavaScript
Open Custom Settings
- TypeScript
- JavaScript
获取 Deep Link
- TypeScript
- JavaScript
发送 Intents (Android)
- TypeScript
- JavaScript
文档
方法
addEventListener()
static addEventListener(
type: 'url',
handler: (event: {url: string}) => void,
): EmitterSubscription;
通过监听 url
事件类型并提供处理程序,为链接更改添加处理程序。
canOpenURL()
static canOpenURL(url: string): Promise<boolean>;
判断设备上是否有已经安装的应用可以处理指定的 URL。
本方法会返回一个Promise
对象。当确定传入的 URL 可以被处理时,promise 就会返回,值的第一个参数是表示是否可以打开 URL。
The Promise
will reject on Android if it was impossible to check if the URL can be opened or when targetting Android 11 (SDK 30) if you didn't specify the relevant intent queries in AndroidManifest.xml
. Similarly on iOS, the promise will reject if you didn't add the specific scheme in the LSApplicationQueriesSchemes
key inside Info.plist
(see bellow).
如果无法检查 URL 是否可以打开,或者当目标为 Android 11 (SDK 30) 平台且您没有在 AndroidManifest.xml
中指定相关的 intent queries,则 Promise
将在 Android 上拒绝。类似地,在 iOS 上,如果你没有在 Info.plist
中的 LSApplicationQueriesSchemes
键中添加特定的 scheme,Promise
将被拒绝(见下文)。
Parameters:
Name | Type | Description |
---|---|---|
url Required | string | The URL to open. |
对于 web 链接来说,协议头("http://", "https://")不能省略!
This method has limitations on iOS 9+. From the official Apple documentation:
- If your app is linked against an earlier version of iOS but is running in iOS 9.0 or later, you can call this method up to 50 times. After reaching that limit, subsequent calls always resolve to
false
. If the user reinstalls or upgrades the app, iOS resets the limit.对于 iOS 9 来说,你需要在
Info.plist
中添加LSApplicationQueriesSchemes
字段,否则canOpenURL
可能一直返回 false。
When targeting Android 11 (SDK 30) you must specify the intents for the schemes you want to handle in
AndroidManifest.xml
. A list of common intents can be found here.For example to handle
https
schemes the following needs to be added to your manifest:<manifest ...>
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https"/>
</intent>
</queries>
</manifest>
getInitialURL()
static getInitialURL(): Promise<string | null>;
If the app launch was triggered by an app link, it will give the link url, otherwise it will give null
.
To support deep linking on Android, refer https://developer.android.com/training/app-indexing/deep-linking.html#handling-intents
getInitialURL may return
null
while debugging is enabled. Disable the debugger to ensure it gets passed.
openSettings()
static openSettings(): Promise<void>;
Open the Settings app and displays the app’s custom settings, if it has any.
openURL()
static openURL(url: string): Promise<any>;
Try to open the given url
with any of the installed apps.
You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386" on Android or "https://maps.apple.com/?ll=37.484847,-122.148386" on iOS), a contact, or any other URL that can be opened with the installed apps.
The method returns a Promise
object. If the user confirms the open dialog or the url automatically opens, the promise is resolved. If the user cancels the open dialog or there are no registered applications for the url, the promise is rejected.
Parameters:
Name | Type | Description |
---|---|---|
url Required | string | The URL to open. |
This method will fail if the system doesn't know how to open the specified URL. If you're passing in a non-http(s) URL, it's best to check
canOpenURL()
first.
For web URLs, the protocol (
"http://"
,"https://"
) must be set accordingly!
This method may behave differently in a simulator e.g.
"tel:"
links are not able to be handled in the iOS simulator as there's no access to the dialer app.
sendIntent()
Android
static sendIntent(
action: string,
extras?: Array<{key: string; value: string | number | boolean}>,
): Promise<void>;
启动 Android intent 时携带 extras。
Parameters:
Name | Type |
---|---|
action Required | string |
extras | Array<{key: string, value: string | number | boolean}> |