This is documentation for the next SDK version. For up-to-date documentation, see the latest version (SDK 55).
Expo 分享
一个提供与其他应用共享和接收数据功能的库。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
expo-sharing 允许你直接与其他兼容应用共享文件,并接收从其他应用共享过来的兼容数据。
Web 上的共享限制
- 用于 web 的
expo-sharing构建于 Web Share API 之上,而该 API 目前仍然只有非常有限的浏览器支持。在调用之前,请务必通过使用Sharing.isAvailableAsync()来检查该 API 是否可用。 - Web 上需要 HTTPS:Web Share API 仅在页面通过 https 提供时才可在 web 上使用。使用
npx expo start --tunnel运行你的应用以启用它。 - Web 上不支持本地文件共享:通过 URI 共享本地文件在 Android 和 iOS 上可行,但在 web 上不可行。你无法在 web 上通过 URI 共享本地文件 — 你需要先把它们上传到某处,然后共享那个 URI。
安装
- npx expo install expo-sharingIf you are installing this in an existing React Native app, make sure to install expo in your project.
在 app 配置中进行配置
如果你在项目中使用了配置插件(Continuous Native Generation (CNG)),你可以使用 expo-sharing 内置的配置插件进行配置。该插件允许你配置一些无法在运行时设置、且需要构建新的应用二进制文件后才会生效的属性。如果你的应用不使用 CNG,那么你需要手动配置该库。
Example app.json with config plugin
以下示例展示了一个可在 Android 和 iOS 上共享单张或多张图片的配置:
{ "expo": { "plugins": [ [ "expo-sharing", { "ios": { "enabled": true, "activationRule": { "supportsImageWithMaxCount": 5 } }, "android": { "enabled": true, "singleShareMimeTypes": ["image/*"], "multipleShareMimeTypes": ["image/*"] } } ] ] } }
Configurable properties
| Name | Default | Description |
|---|---|---|
ios.enabled | false | 一个布尔值,用于启用 iOS Share Extension。如果为 |
ios.extensionBundleIdentifier | {appBundleIdentifier}.ShareExtension | iOS Share Extension 的 bundle identifier。 |
ios.appGroupId | group.{appBundleIdentifier} | 用于在应用和扩展之间共享数据的 App Group ID。 |
ios.activationRule | {} | 用于 Info.plist 中 |
android.enabled | false | 一个布尔值,用于启用 Android 分享 intent 处理。如果为 |
android.singleShareMimeTypes | [] | 一个 MIME 类型数组,用于接受单文件共享(使用 |
android.multipleShareMimeTypes | [] | 一个 MIME 类型数组,用于接受多文件共享(使用 |
从其他应用共享到你的应用
注意:此功能目前处于实验性状态。在 iOS 上,共享扩展会打开主目标,而不是在共享ViewController中处理共享内容,这并未得到 Apple 的官方支持,并且可能在未来的 iOS 版本中失效。
当应用用户向你的应用共享内容时,操作系统会启动你的应用(也称为将其置于前台的过程)。要处理此操作,你需要配置导航以处理传入的深度链接。
Expo Router
如果你正在使用 Expo Router,可以使用 +native-intent.ts 文件来处理传入的共享 intent。这允许你检查传入路径并重定向到特定路由。
import { getSharedPayloads } from 'expo-sharing'; export async function redirectSystemPath({ path, initial }: { path: string; initial: boolean }) { try { // 检查该 URL 是否来自分享扩展/intent if (new URL(path).hostname === 'expo-sharing') { return '/handle-share'; } return path; } catch { // 出错时回退到根路径 return '/'; } }
React Navigation
如果你正在使用 React Navigation,可以使用 linking 属性来拦截深度链接。你应该检查传入 URL 的 hostname 是否匹配 expo-sharing scheme,并将用户重定向到特定的处理屏幕。
import * as Linking from 'expo-linking'; import { createStaticNavigation } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; const RootStack = createNativeStackNavigator({ screens: { // 其他屏幕 HandleShare: { screen: HandleShare, linking: { path: '/handle-share', }, }, }, }); const Navigation = createStaticNavigation(RootStack); function processUrl(url: string | null) { if (!url) return null; // 你的分享处理屏幕的路径 const handlerUrl = Linking.createURL('/handle-share'); // 检查该 URL 是否来自分享扩展/intent if (new URL(url).hostname === 'expo-sharing') { return handlerUrl; } return url; } export default function App() { return ( <Navigation // 其余的导航配置 linking={{ prefixes: [Linking.createURL('/')], async getInitialURL() { const initialUrl = await Linking.getInitialURL(); return processUrl(initialUrl); }, subscribe(listener) { const linkingSubscription = Linking.addEventListener('url', ({ url }) => { const processedUrl = processUrl(url) ?? url; listener(processedUrl); }); return () => { linkingSubscription.remove(); }; }, }} /> ); }
没有导航库
如果你正在创建一个不使用导航库的基础应用,那么你的主屏幕就是处理屏幕。你可以继续阅读下一节。
显示共享内容
一旦你将用户重定向到处理屏幕后,就可以使用 useIncomingShare hook 来访问并显示共享数据。
以下示例展示了一个显示共享图片的屏幕:
import { Image } from 'expo-image'; import { useIncomingShare } from 'expo-sharing'; import { View, StyleSheet, ActivityIndicator } from 'react-native'; export default function ShareReceived() { const { resolvedSharedPayloads, isResolving } = useIncomingShare(); if (isResolving) { return ( <View style={styles.container}> <ActivityIndicator size="large" /> </View> ); } return ( <View style={styles.container}> {resolvedSharedPayloads.map((payload, index) => { if (payload.contentType === 'image') { return <Image source={{ uri: payload.contentUri }} style={styles.image} key={index} />; } return null; })} </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'white', }, image: { width: 300, height: 300, marginBottom: 20, borderRadius: 10, }, });
API
import * as Sharing from 'expo-sharing';
Hooks
Hook, which returns the data shared with the application and updates the data if the shared payload has changed.
UseIncomingShareResultMethods
Returns resolved data shared with the app. Compared to data returned from getSharedPayloads contains additional
information useful for reading and displaying the data. For example, when a web URL is shared with the app,
a resolved payload will contain additional information about the URL contents.
Depending on what has been shared, this method may require a network connection to resolve content details.
Promise<ResolvedSharePayload[]>Returns raw data shared with the app. Returns an empty array if no data has been shared with the app.
SharePayload[]Determine if the sharing API can be used in this app.
Promise<boolean>A promise that fulfills with true if the sharing API can be used, and false otherwise.
| Parameter | Type | Description |
|---|---|---|
| url | string | Local file URL to share. |
| options(optional) | SharingOptions | A map of share options. Default: {} |
Opens action sheet to share file to different applications which can handle this type of file.
Promise<void>Types
Describes a configuration for data types that are possible to share in the application on iOS.
| Property | Type | Description |
|---|---|---|
| supportsAttachmentsWithMaxCount(optional) | number | Determines a maximum number of attachments that can be shared with the app.
When Default: 0 |
| supportsFileWithMaxCount(optional) | number | Determines a maximum number of files that can be shared with the app.
When Default: 0 |
| supportsImageWithMaxCount(optional) | number | Determines a maximum number of images that can be shared with the app.
When Default: 0 |
| supportsMovieWithMaxCount(optional) | number | Determines a maximum number of videos that can be shared with the app.
When Default: 0 |
| supportsText(optional) | boolean | Whether the app should accept shared text. Default: false |
| supportsWebPageWithMaxCount(optional) | number | Determines a maximum number of webpages that can be shared with the app.
When Default: 0 |
| supportsWebUrlWithMaxCount(optional) | number | Determines a maximum number of web URLs that can be shared with the app.
When Default: 0 |
Type: SharePayload extended by:
| Property | Type | Description |
|---|---|---|
| contentMimeType | string | null | Mime type of the content accessible via the |
| contentSize | number | null | Size of the content accessible via the |
| contentType | ContentType | null | Type of the content accessible via the |
| contentUri | string | null | URI which can be used to access the shared content. When resolving contents of a URL with redirects, contains the redirect target URI.
Null when resolving a |
| originalName | string | null | If applicable, value of the |
Literal Type: string
Describes the resolved content type.
Acceptable values are: 'text' | 'audio' | 'image' | 'video' | 'file' | 'website'
Literal Type: union
Represents a payload shared with the app, with additional information about the shared contents.
Acceptable values are: UriBasedResolvedSharePayload | TextBasedResolvedSharePayload
Represents raw data shared with the app.
| Property | Type | Description |
|---|---|---|
| mimeType(optional) | string | The MIME type of the contents of the Default: 'text/plain' |
| shareType(optional) | ShareType | The type of the shared content. Default: 'text' |
| value(optional) | string | The primary value of the content.
Default: "" |
Literal Type: string
Determines the type of content being shared.
text: Plain text content.url: A specific URL.audio: An audio file.image: An image file.video: A video file.file: A generic file.
Acceptable values are: 'text' | 'url' | 'audio' | 'image' | 'video' | 'file'
| Property | Type | Description |
|---|---|---|
| anchor(optional) | {
height: number,
width: number,
x: number,
y: number
} | Only for: iOS Sets the anchor point for iPad |
| dialogTitle(optional) | string | Only for: Android Web Sets share dialog title. |
| mimeType(optional) | string | Only for: Android Sets |
| UTI(optional) | string |
Represents a resolved payload, where a text was shared with the app.
Type: BaseResolvedSharePayload extended by:
| Property | Type | Description |
|---|---|---|
| contentType(optional) | 'text' | - |
Represents a resolved payload, for which the data can be accessed through a URI.
Type: BaseResolvedSharePayload extended by:
| Property | Type | Description |
|---|---|---|
| contentType | 'audio' | 'file' | 'video' | 'image' | 'website' | - |
| contentUri | string | - |
Object returned by useIncomingShare hook containing information about data shared with the app.
| Property | Type | Description |
|---|---|---|
| clearSharedPayloads | () => void | Clears payloads shared with the app. |
| error | Error | null | Contains an error encountered while resolving the shared payload. Null on success. |
| isResolving | boolean | Boolean indicating whether the current shared payloads are being resolved. |
| refreshSharePayloads | () => void | Forces a refresh of the shared payloads. |
| resolvedSharedPayloads | ResolvedSharePayload[] | Contains an array of resolved payloads shared with the app. Returns an empty array if the shared payloads are being resolved or if the resolving has failed. |
| sharedPayloads | SharePayload[] | Returns unresolved payloads shared with the app. Synchronous and available immediately after creating the hook. |