如何让React Native应用出现在分享面板建议并处理共享数据?
React Native 接收其他应用共享内容实现指南
要让你的React Native应用出现在系统分享面板并处理外部共享数据,需要分别完成iOS/Android平台的配置和JS层的数据监听与处理,以下是具体步骤:
一、配置应用使其显示在分享面板
1. iOS 平台配置
(1)修改Info.plist
打开项目的ios/[你的项目名]/Info.plist文件,添加以下配置以支持接收不同类型的共享内容(文本、图片、文件等):
<!-- 自定义URL Scheme,用于接收通过链接传递的共享数据 --> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>myappshare</string> <!-- 替换成你的自定义Scheme,如appname-share --> </array> </dict> </array> <!-- 支持系统通用共享场景 --> <key>NSUserActivityTypes</key> <array> <string>com.apple.corespotlightitem</string> </array> <!-- 配置可接收的内容类型(示例:文本、图片) --> <key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeName</key> <string>Plain Text</string> <key>LSHandlerRank</key> <string>Alternate</string> <key>LSItemContentTypes</key> <array> <string>public.plain-text</string> </array> </dict> <dict> <key>CFBundleTypeName</key> <string>Image Files</string> <key>LSHandlerRank</key> <string>Alternate</string> <key>LSItemContentTypes</key> <array> <string>public.image</string> </array> </dict> </array>
(2)处理AppDelegate中的共享回调
在AppDelegate.swift(或AppDelegate.m)中添加代码,捕获共享数据并通知JS层:
import UIKit import React @main class AppDelegate: UIResponder, UIApplicationDelegate, RCTBridgeDelegate { var bridge: RCTBridge! var window: UIWindow? private var sharedData: [String: Any]? func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { // 解析URL中的共享参数 let queryParams = url.queryParameters ?? [:] sharedData = queryParams notifyJSOfSharedData() return RCTLinkingManager.application(app, open: url, options: options) } func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { // 处理通用链接或系统共享的内容 if userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL { sharedData = ["type": "url", "content": url.absoluteString] notifyJSOfSharedData() } return RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler) } // 发送通知到JS层 private func notifyJSOfSharedData() { guard let data = sharedData else { return } NotificationCenter.default.post(name: NSNotification.Name("SharedDataReceived"), object: data) } } // 扩展:解析URL参数 extension URL { var queryParameters: [String: String]? { guard let components = URLComponents(url: self, resolvingAgainstBaseURL: true), let queryItems = components.queryItems else { return nil } return queryItems.reduce(into: [String: String]()) { (result, item) in result[item.name] = item.value } } }
2. Android 平台配置
(1)修改AndroidManifest.xml
打开android/app/src/main/AndroidManifest.xml,在主Activity标签内添加intent-filter,声明应用可接收的共享类型:
<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize"> <!-- 接收单条文本 --> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> <!-- 接收单张图片 --> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-filter> <!-- 接收多张图片 --> <intent-filter> <action android:name="android.intent.action.SEND_MULTIPLE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-filter> </activity>
(2)在MainActivity中处理共享数据
在MainActivity.kt(或MainActivity.java)中捕获Intent中的共享数据,并发送到JS层:
import android.content.Intent import android.net.Uri import com.facebook.react.ReactActivity import com.facebook.react.defaults.DefaultReactActivityDelegate import com.facebook.react.modules.core.DeviceEventManagerModule class MainActivity : ReactActivity() { private var sharedData: HashMap<String, Any>? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) handleIncomingIntent(intent) } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) setIntent(intent) handleIncomingIntent(intent) } private fun handleIncomingIntent(intent: Intent?) { intent?.let { when (it.action) { Intent.ACTION_SEND -> { val mimeType = it.type when { mimeType?.startsWith("text/") == true -> { val text = it.getStringExtra(Intent.EXTRA_TEXT) sharedData = hashMapOf("type" to "text", "content" to text) } mimeType?.startsWith("image/") == true -> { val imageUri = it.getParcelableExtra<Uri>(Intent.EXTRA_STREAM) imageUri?.let { uri -> sharedData = hashMapOf("type" to "image", "uri" to uri.toString()) } } } sharedData?.let { data -> sendDataToJS(data) } } Intent.ACTION_SEND_MULTIPLE -> { val mimeType = it.type if (mimeType?.startsWith("image/") == true) { val imageUris = it.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM) imageUris?.let { uris -> val uriStrings = uris.map { it.toString() } sharedData = hashMapOf("type" to "multiple_images", "uris" to uriStrings) sendDataToJS(sharedData!!) } } } } } } // 发送数据到JS层 private fun sendDataToJS(data: HashMap<String, Any>) { reactInstanceManager.currentReactContext?.let { context -> context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit("SharedDataReceived", data) } } override fun createReactActivityDelegate() = DefaultReactActivityDelegate( this, mainComponentName, fabricEnabled = false ) }
二、JS层监听并处理共享数据
在React Native的JS代码中,通过事件监听获取Native传递的共享数据:
import { useEffect, useState } from 'react'; import { View, Text, DeviceEventEmitter, Linking } from 'react-native'; const App = () => { const [sharedContent, setSharedContent] = useState(null); useEffect(() => { // 监听Android平台的共享事件 const androidSubscription = DeviceEventEmitter.addListener( 'SharedDataReceived', (data) => { setSharedContent(data); console.log('收到Android共享数据:', data); // 这里可以添加数据处理逻辑,比如存储、展示等 } ); // 监听iOS平台的URL跳转事件 const iosSubscription = Linking.addEventListener('url', (event) => { const url = new URL(event.url); const params = Object.fromEntries(url.searchParams.entries()); const data = { type: 'text', content: params.text || params.url }; setSharedContent(data); console.log('收到iOS共享数据:', data); }); // 检查应用启动时是否携带共享数据 const checkInitialData = async () => { const initialUrl = await Linking.getInitialURL(); if (initialUrl) { const url = new URL(initialUrl); const params = Object.fromEntries(url.searchParams.entries()); setSharedContent({ type: 'text', content: params.text || params.url }); } }; checkInitialData(); // 清理监听 return () => { androidSubscription.remove(); iosSubscription.remove(); }; }, []); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 }}> {sharedContent ? ( <Text style={{ fontSize: 16 }}> 收到共享内容:\n{JSON.stringify(sharedContent, null, 2)} </Text> ) : ( <Text style={{ fontSize: 16 }}>等待接收共享内容...</Text> )} </View> ); }; export default App;
关键注意事项
- iOS平台:如果需要接收更多类型的文件,需在
Info.plist中添加对应的UTI(统一类型标识符),可参考苹果官方的UTI列表。 - Android平台:Android 10及以上版本处理文件URI时,需使用
ContentResolver获取文件内容,避免直接访问路径导致权限问题。 - 测试方法:打开相册、浏览器等应用,选择内容后点击分享,即可在面板中看到你的应用。
内容的提问来源于stack exchange,提问作者Leri Gogsadze
相关产品推荐
相关产品推荐

