I want to use Share functionally in my React Native application but there is one exception, I don't want to share a content from my app, I want to share content from another app to my app, how is it possible to show my App in share sheet suggestions and handle shared data?
3 Answers
Adding your own Share Extension (iOS) or Share Intent (Android) to a React Native app is a little tricky, unfortunately. On iOS for example, this requires setting up a whole app extension including some native code which often ends up very decoupled from the rest of the React Native app.
See here for Android documentation and here for iOS documentation on the native parts.
There are some third-party libraries like react-native-share-extension that make this somewhat easier, even though it still requires some set-up. If you're using Expo, all solutions might end up being problematic due to the required app extension on iOS which might even be complex to setup using Expo config plugins (even though it's probably possible!).
Another problem you might face is that, at least on iOS, the amount of memory a Share Extension can use is very limited for a React Native app. Even a very basic extension might be killed by the OS due to an out of memory signal. A relatively easy way (which still requires a lot of native code) to circumvent this might be to simply link into your app once someone clicks on your share extension, instead of adding actual native UI for the modal of the iOS extension (which requires more memory). Here's a Medium article of someone who's done this already (and faced the same issues).
1 Comment
i used this package to implement share extension for both ios and android . https://github.com/meedan/react-native-share-menu
3 Comments
1. Add the following to your AndroidManifest.xml inside application > activity
<intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-filter> 2. Inside android/app/src/main/java/com/yourapp/ create two file
SharedImageModule.java
package com.awesomeproject; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.Arguments; import android.content.Intent; import android.net.Uri; import android.content.SharedPreferences; import android.content.Context; public class SharedImageModule extends ReactContextBaseJavaModule { private static ReactApplicationContext reactContext; private static final String PREFS_NAME = "SharedImagePrefs"; private static final String KEY_SHARED_IMAGE_URI = "sharedImageUri"; public SharedImageModule(ReactApplicationContext context) { super(context); reactContext = context; } @Override public String getName() { return "SharedImageModule"; } public static void handleIntent(Intent intent) { if (intent.hasExtra(Intent.EXTRA_STREAM)) { Uri sharedImageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM); if (sharedImageUri != null && reactContext != null) { saveSharedImageUri(sharedImageUri.toString()); } } } private static void saveSharedImageUri(String uri) { SharedPreferences prefs = reactContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putString(KEY_SHARED_IMAGE_URI, uri); editor.apply(); } private static String getStoredSharedImageUri() { SharedPreferences prefs = reactContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); return prefs.getString(KEY_SHARED_IMAGE_URI, null); } @ReactMethod public void getSharedImage(Promise promise) { WritableMap map = Arguments.createMap(); String storedUri = getStoredSharedImageUri(); if (storedUri != null) { map.putString("type", "image"); map.putString("value", storedUri); promise.resolve(map); } else { promise.resolve(null); } } @ReactMethod public void clearSharedImage(Promise promise) { SharedPreferences prefs = reactContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.remove(KEY_SHARED_IMAGE_URI); editor.apply(); promise.resolve(true); } } SharedImagePackage.java
package com.awesomeproject; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class SharedImagePackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new SharedImageModule(reactContext)); return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } } 3. In MainApplication.java file add below code
import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.Collections; Inside getPackages
packages.add(new SharedImagePackage()); 4. Modify MainActivity.java
import android.content.Intent; import android.os.Handler; import android.os.Looper; Inside onCreate
// Delay intent handling to ensure React Native is initialized new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { @Override public void run() { Intent intent = getIntent(); if (intent != null && Intent.ACTION_SEND.equals(intent.getAction()) && intent.getType() != null) { if (intent.getType().startsWith("image/")) { SharedImageModule.handleIntent(intent); // Clear the intent after processing to avoid duplicates setIntent(new Intent()); } } } }, 3000); // 1-second delay Inside MainActivity
@Override public void onNewIntent(Intent intent) { super.onNewIntent(intent); handleIntent(intent); } private void handleIntent(Intent intent) { String action = intent.getAction(); String type = intent.getType(); if (Intent.ACTION_SEND.equals(action) && type != null) { if (type.startsWith("image/")) { SharedImageModule.handleIntent(intent); // Clear the intent after processing to avoid duplicates setIntent(new Intent()); } } } 5. React-native side code for getting/removing images
import React, { useEffect, useState } from "react"; import { View, Image, Text, Button, NativeModules } from "react-native"; const { SharedImageModule } = NativeModules; const App = () => { const [sharedImage, setSharedImage] = useState(null); useEffect(() => { fetchSharedImage(); }, []); const fetchSharedImage = async () => { SharedImageModule.getSharedImage() .then((result) => { if (result?.type === "image" && result?.value) { console.log("Shared image:", result.value); setSharedImage(result.value); } }) .catch(console.error); }; const removeSharedImage = async () => { SharedImageModule.clearSharedImage() .then(() => { setSharedImage(null); console.log("Shared image cleared"); }) .catch(console.error); }; return ( <View style={{ flex: 1, alignItems: "center", paddingTop: 50 }}> {sharedImage ? ( <> <Image source={{ uri: sharedImage }} style={{ width: 400, height: 400, resizeMode: "contain" }} /> <Button title="Remove Image" onPress={removeSharedImage} /> </> ) : ( <> <Text>No image shared</Text> <Button title="Get Image" onPress={fetchSharedImage} /> </> )} </View> ); }; export default App;