提供对系统 Web 浏览器的访问并支持处理重定向的库。
expo-web-browser
提供对系统 Web 浏览器的访问并支持处理重定向。在 Android 上,它使用 ChromeCustomTabs
,在 iOS 上,它使用 SFSafariViewController
或 SFAuthenticationSession
,具体取决于你调用的方法。从 iOS 11 开始,SFSafariViewController
不再与 Safari 共享 cookie,因此如果你使用 WebBrowser
进行身份验证,你将需要使用 WebBrowser.openAuthSessionAsync
,如果你只想打开网页(例如你的应用隐私政策),请使用 WebBrowser.openBrowserAsync
。
¥expo-web-browser
provides access to the system's web browser and supports handling redirects. On Android, it uses ChromeCustomTabs
and on iOS, it uses SFSafariViewController
or SFAuthenticationSession
, depending on the method you call. As of iOS 11, SFSafariViewController
no longer shares cookies with Safari, so if you are using WebBrowser
for authentication you will want to use WebBrowser.openAuthSessionAsync
, and if you just want to open a webpage (such as your app privacy policy), then use WebBrowser.openBrowserAsync
.
¥Installation
-
npx expo install expo-web-browser
If you are installing this in an existing React Native app (bare workflow), start by installing expo
in your project. Then, follow the additional instructions as mentioned by library's README under "Installation in bare React Native projects" section.
¥Usage
import React, { useState } from 'react';
import { Button, Text, View, StyleSheet } from 'react-native';
import * as WebBrowser from 'expo-web-browser';
%%placeholder-start%%%%placeholder-end%%import Constants from 'expo-constants';
export default function App() {
const [result, setResult] = useState(null);
const _handlePressButtonAsync = async () => {
let result = await WebBrowser.openBrowserAsync('https://expo.dev');
setResult(result);
};
return (
<View style={styles.container}>
<Button title="Open WebBrowser" onPress={_handlePressButtonAsync} />
<Text>{result && JSON.stringify(result)}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
¥Handling deep links from the WebBrowser
如果你使用 WebBrowser
窗口进行身份验证,或者希望通过深层链接将信息传回应用的其他用例,请在打开浏览器之前添加带有 Linking.addEventListener
的处理程序。当监听器触发时,你应该调用 dismissBrowser
。当处理深层链接时,它不会自动被忽略。除此之外,来自 WebBrowser
的重定向与其他深层链接的工作方式相同。请阅读 链接 了解更多相关信息。
¥If you use the WebBrowser
window for authentication or another use case where you want to pass information back into your app through a deep link, add a handler with Linking.addEventListener
before opening the browser. When the listener fires, you should call dismissBrowser
. It will not automatically be dismissed when a deep link is handled. Aside from that, redirects from WebBrowser
work the same as other deep links. Read more about it in Linking.
import * as WebBrowser from 'expo-web-browser';
WebBrowser.coolDownAsync(browserPackage)
Name | Type | Description |
---|---|---|
browserPackage (optional) | string | Package of browser to be cooled. If not set, preferred browser will be used. |
This methods removes all bindings to services created by warmUpAsync
or mayInitWithUrlAsync
. You should call
this method once you don't need them to avoid potential memory leaks. However, those binding
would be cleared once your application is destroyed, which might be sufficient in most cases.
The promise which fulfils with WebBrowserCoolDownResult
when cooling is performed, or
an empty object when there was no connection to be dismissed.
WebBrowser.dismissAuthSession()
void
WebBrowser.dismissBrowser()
Dismisses the presented web browser.
void
The void
on successful attempt, or throws error, if dismiss functionality is not avaiable.
WebBrowser.getCustomTabsSupportingBrowsersAsync()
Returns a list of applications package names supporting Custom Tabs, Custom Tabs
service, user chosen and preferred one. This may not be fully reliable, since it uses
PackageManager.getResolvingActivities
under the hood. (For example, some browsers might not be
present in browserPackages list once another browser is set to default.)
The promise which fulfils with WebBrowserCustomTabsResults
object.
WebBrowser.mayInitWithUrlAsync(url, browserPackage)
Name | Type | Description |
---|---|---|
url | string | The url of page that is likely to be loaded first when opening browser. |
browserPackage (optional) | string | Package of browser to be informed. If not set, preferred browser will be used. |
This method initiates (if needed) CustomTabsSession
and calls its mayLaunchUrl
method for browser specified by the package.
A promise which fulfils with WebBrowserMayInitWithUrlResult
object.
WebBrowser.maybeCompleteAuthSession(options)
Name | Type |
---|---|
options (optional) | WebBrowserCompleteAuthSessionOptions |
Possibly completes an authentication session on web in a window popup. The method should be invoked on the page that the window redirects to.
Returns an object with message about why the redirect failed or succeeded:
If type
is set to failed
, the reason depends on the message:
Not supported on this platform
: If the platform doesn't support this method (iOS, Android).Cannot use expo-web-browser in a non-browser environment
: If the code was executed in an SSR
or node environment.No auth session is currently in progress
: (the cached state wasn't found in local storage).
This can happen if the window redirects to an origin (website) that is different to the initial
website origin. If this happens in development, it may be because the auth started on localhost
and finished on your computer port (Ex: 128.0.0.*
). This is controlled by the redirectUrl
and returnUrl
.Current URL "<URL>" and original redirect URL "<URL>" do not match
: This can occur when the
redirect URL doesn't match what was initial defined as the returnUrl
. You can skip this test
in development by passing { skipRedirectCheck: true }
to the function.If type
is set to success
, the parent window will attempt to close the child window immediately.
If the error ERR_WEB_BROWSER_REDIRECT
was thrown, it may mean that the parent window was
reloaded before the auth was completed. In this case you'll need to close the child window manually.
WebBrowser.openAuthSessionAsync(url, redirectUrl, options)
Name | Type | Description |
---|---|---|
url | string | The url to open in the web browser. This should be a login page. |
redirectUrl (optional) | null | string | Optional - The url to deep link back into your app.
On web, this defaults to the output of |
options (optional) | AuthSessionOpenOptions | Optional - An object extending the Default: {} |
This will be done using a "custom Chrome tabs" browser, AppState, and Linking APIs.
Opens the url with Safari in a modal using ASWebAuthenticationSession
. The user will be asked
whether to allow the app to authenticate using the given url.
To handle redirection back to the mobile application, the redirect URI set in the authentication server
has to use the protocol provided as the scheme in app.json expo.scheme
.
For example, demo://
not https://
protocol.
Using Linking.addEventListener
is not needed and can have side effects.
This API can only be used in a secure environment (localhost/https). to test this. Otherwise, an error with code
ERR_WEB_BROWSER_CRYPTO
will be thrown. This will use the browser'swindow.open()
API.
WebBrowser.maybeCompleteAuthSession()
.WebBrowser.maybeCompleteAuthSession()
.How this works on web:
npx expo start --https
localstorage
. This ensures that auth cannot complete
unless it's done from a page running with the same origin as it was started.
Ex: if openAuthSessionAsync
is invoked on https://localhost:19006
, then maybeCompleteAuthSession
must be invoked on a page hosted from the origin https://localhost:19006
. Using a different
website, or even a different host like https://128.0.0.*:19006
for example will not work.{ type: 'dismiss' }
.On mobile web, Chrome and Safari will block any call to
window.open()
which takes too long to fire after a user interaction. This method must be invoked immediately after a user interaction. If the event is blocked, an error with codeERR_WEB_BROWSER_BLOCKED
will be thrown.
{ type: 'cancel' }
object.{ type: 'cancel' }
object.dismissBrowser
,
the Promise fulfills with { type: 'dismiss' }
object.WebBrowser.openBrowserAsync(url, browserParams)
Name | Type | Description |
---|---|---|
url | string | The url to open in the web browser. |
browserParams (optional) | WebBrowserOpenOptions | A dictionary of key-value pairs. Default: {} |
Opens the url with Safari in a modal on iOS using SFSafariViewController
,
and Chrome in a new custom tab
on Android. On iOS, the modal Safari will not share cookies with the system Safari. If you need
this, use openAuthSessionAsync
.
The promise behaves differently based on the platform.
On Android promise resolves with { type: 'opened' }
if we were able to open browser.
On iOS:
{ type: 'cancel' }
.dismissBrowser
, the Promise resolves with { type: 'dismiss' }
.WebBrowser.warmUpAsync(browserPackage)
Name | Type | Description |
---|---|---|
browserPackage (optional) | string | Package of browser to be warmed up. If not set, preferred browser will be warmed. |
This method calls warmUp
method on CustomTabsClient
for specified package.
A promise which fulfils with WebBrowserWarmUpResult
object.
AuthSessionOpenOptions
If there is no native AuthSession implementation available (which is the case on Android) the params inherited from
WebBrowserOpenOptions
will be used in the browser polyfill. Otherwise, the browser parameters will be ignored.
Type: WebBrowserOpenOptions
extended by:
Name | Type | Description |
---|---|---|
preferEphemeralSession (optional) | boolean | Only for: iOS Determines whether the session should ask the browser for a private authentication session.
Set this to Default: false |
WebBrowserAuthSessionResult
Literal Type: multiple types
Acceptable values are: WebBrowserRedirectResult
| WebBrowserResult
WebBrowserCompleteAuthSessionOptions
Name | Type | Description |
---|---|---|
skipRedirectCheck (optional) | boolean | Attempt to close the window without checking to see if the auth redirect matches the cached redirect URL. |
WebBrowserCompleteAuthSessionResult
Name | Type | Description |
---|---|---|
message | string | Additional description or reasoning of the result. |
type | 'success' | 'failed' | Type of the result. |
WebBrowserCoolDownResult
Type: ServiceActionResult
WebBrowserCustomTabsResults
Name | Type | Description |
---|---|---|
browserPackages | string[] | All packages recognized by |
defaultBrowserPackage (optional) | string | Default package chosen by user, |
preferredBrowserPackage (optional) | string | Package preferred by |
servicePackages | string[] | All packages recognized by |
WebBrowserMayInitWithUrlResult
Type: ServiceActionResult
WebBrowserOpenOptions
Name | Type | Description |
---|---|---|
browserPackage (optional) | string | Only for: Android Package name of a browser to be used to handle Custom Tabs. List of
available packages is to be queried by |
controlsColor (optional) | string | Only for: iOS Tint color for controls in SKSafariViewController. Supports React Native color formats. |
createTask (optional) | boolean | Only for: Android A boolean determining whether the browser should open in a new task or in the same task as your app. Default: true |
dismissButtonStyle (optional) | 'done' | 'close' | 'cancel' | Only for: iOS The style of the dismiss button. Should be one of: |
enableBarCollapsing (optional) | boolean | A boolean determining whether the toolbar should be hiding when a user scrolls the website. |
enableDefaultShareMenuItem (optional) | boolean | Only for: Android A boolean determining whether a default share item should be added to the menu. |
presentationStyle (optional) | WebBrowserPresentationStyle | Only for: iOS The presentation style of the browser window. Default: WebBrowser.WebBrowserPresentationStyle.OverFullScreen |
readerMode (optional) | boolean | Only for: iOS A boolean determining whether Safari should enter Reader mode, if it is available. |
secondaryToolbarColor (optional) | string | Only for: Android Color of the secondary toolbar. Supports React Native color formats. |
showInRecents (optional) | boolean | Only for: Android A boolean determining whether browsed website should be shown as separate
entry in Android recents/multitasking view. Requires Default: false |
showTitle (optional) | boolean | Only for: Android A boolean determining whether the browser should show the title of website on the toolbar. |
toolbarColor (optional) | string | Color of the toolbar. Supports React Native color formats. |
windowFeatures (optional) | string | WebBrowserWindowFeatures | Only for: Web Features to use with |
windowName (optional) | string | Only for: Web Name to assign to the popup window. |
WebBrowserRedirectResult
Name | Type | Description |
---|---|---|
type | 'success' | Type of the result. |
url | string | - |
WebBrowserResult
Name | Type | Description |
---|---|---|
type | WebBrowserResultType | Type of the result. |
WebBrowserWarmUpResult
Type: ServiceActionResult
WebBrowserWindowFeatures
Type: Record<string, number | boolean | string>
WebBrowserPresentationStyle
A browser presentation style. Its values are directly mapped to the UIModalPresentationStyle
.
WebBrowserPresentationStyle Values
AUTOMATIC
WebBrowserPresentationStyle.AUTOMATIC = "automatic"
The default presentation style chosen by the system.
On older iOS versions, falls back to WebBrowserPresentationStyle.FullScreen
.
CURRENT_CONTEXT
WebBrowserPresentationStyle.CURRENT_CONTEXT = "currentContext"
A presentation style where the browser is displayed over the app's content.
FORM_SHEET
WebBrowserPresentationStyle.FORM_SHEET = "formSheet"
A presentation style that displays the browser centered in the screen.
FULL_SCREEN
WebBrowserPresentationStyle.FULL_SCREEN = "fullScreen"
A presentation style in which the presented browser covers the screen.
OVER_CURRENT_CONTEXT
WebBrowserPresentationStyle.OVER_CURRENT_CONTEXT = "overCurrentContext"
A presentation style where the browser is displayed over the app's content.
OVER_FULL_SCREEN
WebBrowserPresentationStyle.OVER_FULL_SCREEN = "overFullScreen"
A presentation style in which the browser view covers the screen.
PAGE_SHEET
WebBrowserPresentationStyle.PAGE_SHEET = "pageSheet"
A presentation style that partially covers the underlying content.
POPOVER
WebBrowserPresentationStyle.POPOVER = "popover"
A presentation style where the browser is displayed in a popover view.
WebBrowserResultType
WebBrowserResultType Values
LOCKED
WebBrowserResultType.LOCKED = "locked"
¥Error codes
ERR_WEB_BROWSER_REDIRECT
仅限网络:窗口无法完成重定向请求,因为调用窗口没有对其父级的引用。如果重新加载父窗口,就会发生这种情况。
¥Web only: The window cannot complete the redirect request because the invoking window doesn't have a reference to its parent. This can happen if the parent window was reloaded.
ERR_WEB_BROWSER_BLOCKED
仅限网络:弹出窗口被浏览器阻止或无法打开。当用户输入被触发后太长时间调用 window.open()
方法时,移动浏览器中可能会发生这种情况。
¥Web only: The popup window was blocked by the browser or failed to open. This can happen in mobile browsers when the window.open()
method was invoked too long after a user input was fired.
移动浏览器这样做是为了防止恶意网站在移动设备上打开许多不需要的弹出窗口。
¥Mobile browsers do this to prevent malicious websites from opening many unwanted popups on mobile.
你的方法仍然可以在异步函数中运行,但在它之前不能有任何长时间运行的任务。你可以使用钩子来禁用用户输入,直到任何其他进程完成加载。
¥You're method can still run in an async function but there cannot be any long running tasks before it. You can use hooks to disable user-inputs until any other processes have finished loading.
ERR_WEB_BROWSER_CRYPTO
仅限网络:当前环境不支持加密。确保你从安全源 (localhost/https) 运行。
¥Web only: The current environment doesn't support crypto. Ensure you are running from a secure origin (localhost/https).