This is not an official Expo SDK package.
Allow sharing URL, text, images, videos and files to your iOS and Android app, using a simple native module for Expo (React Native)
Ensure you use versions that work together
Expo | Supported expo-share-intent version |
---|---|
SDK 52 | 3.0+ |
SDK 51 | 2.0+ |
SDK 50 | 1.0+ |
SDK 49 | 0.2+ |
iOS privacy manifest is available since v1.4.1
Install npm package
yarn add expo-share-intent
# or
npm install expo-share-intent
Requirement: patch-package
For the moment this package need a post-install script
patches
project directory (like example)package.json
"scripts": {
...
"postinstall": "patch-package"
},
patch-package
for auto patchingyarn add patch-package
Requirement: expo-linking
Since Expo52, you also need to install expo-linking
in your app :
expo install expo-linking
Into your app.json
:
"plugins": [
"expo-share-intent"
],
by default only text and url sharing is activated
"scheme": "my-app"
More info here : Linking to your app
Run your app in dev-client
expo prebuild --no-install --clean
expo run:ios
expo run:android
We cannot use expo go with this package, more info here
Make sure to use the hook in your main App.tsx
component before any other Provider :
import { useShareIntent } from "expo-share-intent";
const { hasShareIntent, shareIntent, resetShareIntent, error } =
useShareIntent();
See App.tsx for more details
When dealing with multiple screens and providers your may use ShareIntentProvider
and it's specific hook useShareIntentContext
. Must be in your top component (App.tsx
) before any other Provider :
import { ShareIntentProvider, useShareIntentContext } from "expo-share-intent";
const Home = () => {
const { hasShareIntent, shareIntent, resetShareIntent, error } = useShareIntentContext();
return ...
}
export default const App = () => {
return (
<ShareIntentProvider>
<ThirdPartyExtraProvider>
<Home />
</ThirdPartyExtraProvider>
</ShareIntentProvider>
)
}
const { shareIntent } = useShareIntent();
attribute | description | example |
---|---|---|
shareIntent.text |
raw text from text/weburl (ios) and text/* (android) | "some text ", "http://example.com ", "Hey, Click on my link : http://example.com/nickname " |
shareIntent.webUrl |
link extracted from raw text | null , "http://example.com ", "http://example.com/nickname " |
shareIntent.files |
image / movies / audio / files with name, path, mimetype, size (in octets) and image/video dimensions (width/height/duration) | [{ path: "file:///local/path/filename", mimeType: "image/jpeg", fileName: "originalFilename.jpg", size: 2567402, width: 800, height: 600 }, { path: "file:///local/path/filename", mimeType: "video/mp4", fileName: "originalFilename.mp4", size: 2567402, width: 800, height: 600, duration: 20000 }] |
shareIntent.meta |
meta object which contains extra information about the share intent | { title: "My cool blog article" } |
shareIntent.meta.title |
optional title property sent by other app. Currently only filled on Android | My cool blog article |
app.json
Simply choose content types you need :
"plugins": [
[
"expo-share-intent",
{
"iosActivationRules": {
"NSExtensionActivationSupportsWebURLWithMaxCount": 1,
"NSExtensionActivationSupportsWebPageWithMaxCount": 1,
"NSExtensionActivationSupportsImageWithMaxCount": 1,
"NSExtensionActivationSupportsMovieWithMaxCount": 1,
},
"androidIntentFilters": ["text/*", "image/*"]
}
],
],
Option | Values |
---|---|
iosActivationRules | Allow text sharing with "NSExtensionActivationSupportsText": true Url sharing with "NSExtensionActivationSupportsWebURLWithMaxCount": 1 and "NSExtensionActivationSupportsWebPageWithMaxCount": 1 Images sharing with "NSExtensionActivationSupportsImageWithMaxCount": 1 Videos sharing with "NSExtensionActivationSupportsMovieWithMaxCount": 1 Files and audio sharing with "NSExtensionActivationSupportsFileWithMaxCount": 1 default value: { "NSExtensionActivationSupportsWebURLWithMaxCount": 1, "NSExtensionActivationSupportsWebPageWithMaxCount": 1 }" _More info in apple developper doc here_ you can also provide a custom query (ex: "iosActivationRules": "SUBQUERY (...)" ) |
androidIntentFilters | one file sharing array of MIME types :"text/*" / "image/*" / "video/*" / "*/*" default value: ["text/*"] (text and url) |
androidMultiIntentFilters | multiple files sharing array of MIME types : "image/*" / "video/*" / "audio/* / "*/*" default value: [] |
androidMainActivityAttributes | default value: { "android:launchMode": "singleTask" } |
disableAndroid | Disable the android share intent. Useful if you want to use a custom implementation. default value: false |
disableIOS | Disable the ios share extension. Useful if you want to use a custom implementation (ex: iOS custom view). default value: false |
With expo-router
you need to handle loading elements on Layout. It's the only way to call the native module using deeplink url.
An example is available with Expo Router v3 in example/expo-router
If you want to handle share intent with React Navigation v6, you must use the ShareIntentProvider
and add a custom mapping function in your linking configuration.
Take a look at the example in example/react-navigation.
When building on EAS you should only have one extension target (during credentials setting process).
To avoid expo auto configuration to add an experimental "appExtensions" to app.json
you must manually configure your eas build (projectId in app.json
and a eas.json
file).
More details in #1
$ yarn prebuild
β § Running prebuild[expo-share-intent] add ios share extension (scheme:exposhareintentexample appIdentifier:expo.modules.exposhareintent.example)
β Running prebuild[expo-share-intent] add android filters text/* image/*
β Config sync failed
TypeError: [ios.xcodeproj]: withIosXcodeprojBaseMod: Cannot read properties of null (reading 'path')
This package need a post-install script, see xcode+3.0.1.patch
file in example/patches (more info #31 and #13)
We are using native code to make share intent works, so we can't use Expo Go and have to use a custom dev client, that's why the demo use expo prebuild --no-install
command and then expo run:ios
, instead of a simple expo start --ios
-> More information here
That way you can test your share intent into simulator, but that does not exempt you to test a complete build on device at the end of your development process to make sure all works as excepted.
NB: don't commit your ios/ and android/ folder, rebuild it before EAS build.
If you want to open your application in expo go with this package your can disable the native module call with
useShareIntent({ disabled: true })
. Allowing to speed test other features on your app without share intent.
When using @react-native-google-signin/google-signin
you need to configure a custom scheme in your app.json to handle google signin fallback. By doing this, the original app scheme is deleted and must be manually reassigned :
"scheme": "exposhareintentexample",
"ios": {
"supportsTablet": true,
"bundleIdentifier": "expo.modules.exposhareintent.example",
"infoPlist": {
"CFBundleURLTypes": [
{
"CFBundleURLSchemes": [
"com.googleusercontent.apps.xxxxxxxx-xxxxxxxxx",
"exposhareintentexample"
]
}
]
}
},
At the moment, this project does not support iOS custom view (native view in share intent context). Everything must be handle into React Native code.
I am considering adding the implementation of this custom view in the future !
if it's a must have feature for you, take a look at react-native-share-menu
Enjoying this project? Wanna show some love? Drop a star and consider buying me a coffee to keep me fueled and motivated for the next releases
Are you using expo-share-intent at work? Please consider sponsoring me!
Special thanks to expo-config-plugin-ios-share-extension and react-native-receive-sharing-intent, on which this one is very inspired.