This is a helper module which brings react native as an engine to drive share extension for your app.
installation should be very easy by just installing it from npm.
npm install react-native-share-extension --savethe setup requires a little bit more work. I will try to describe as detail as possible. I would love to use rnpm so I will welcome pull request.
- click on your project's name
- click on
+sign
- select
Share ExtensionunderiOS > Application Extension
- select a name for your new share extension, in my case I chose
MyShareEx
- delete both
ShareViewController.handShareViewController.m. make sure to click onMove to Trashbutton during deletion.
- create new file under your share extension group. in my case it was
MyShareEx
- make sure the type of that object is
Objective-c Fileand name itMyShareEx.m
- since we deleted
ShareViewController.m, we need to tell the storyboard of your share extension where the view needs to be loaded. So click onMainInterface.storyboardand replace the class field fromShareViewControllertoMyShareEx
- now it's time to add our library. Right click on
Librariesgroup and selectAdd Files to "Sample1"...
- select
node_modules>react-native-share-extension>ios>ReactNativeShareExtension.xcodeproj
- now we need to tell the share extension that we want to read new header files. click on project name, in my case
Sample1then click onMyShareEx. After that click on Build Settings and search forHeader Search Paths
- add the new path
$(SRCROOT)/../node_modules/react-native-share-extension/ioswithrecursiveselected.
- we need to add some flags as well, so search for
Other Linker Flagsand add-ObjCand-lc++
- we also need to add all the static libraries such as react and Share Extension. so select
Generaltab and underLinked frameworks and Librariesclick on+and add all of the selected static binaries there.
- we need to modify
MyShareEx/Info.plistto make sure that our share extension can connect to ineternet. This is useful if you need your share extension connects to your api server or react-native remote server dev. For doing that we need toApp Transport Security SettingstoInfo.plist
- now go back to
MyShareEx.mand paste the following code there.
#import <Foundation/Foundation.h>
#import "ReactNativeShareExtension.h"
#import "RCTBundleURLProvider.h"
#import "RCTRootView.h"
@interface MyShareEx : ReactNativeShareExtension
@end
@implementation MyShareEx
RCT_EXPORT_MODULE();
- (UIView*) shareView {
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"MyShareEx"
initialProperties:nil
launchOptions:nil];
rootView.backgroundColor = nil;
return rootView;
}
@end- now try to build the project. it should build successfully.
- edit
android/settings.gradlefile and add the following
include ':app', ':react-native-share-extension'
project(':react-native-share-extension').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share-extension/android')
- edit
android/app/build.gradleand add the following line before react section in dependency
dependencies {
...
compile project(':react-native-share-extension')
compile "com.facebook.react:react-native:+"
}
-
create a folder called
shareunder your java project and create two files. Call themShareActivity.javaandShareApplication.java....just like your main project. -
ShareActivity should look like this
// define your share project, if your main project is com.sample1, then com.sample1.share makes sense....
package com.sample1.share;
// import ReactActivity
import com.facebook.react.ReactActivity;
public class ShareActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
// this is the name AppRegistry will use to launch the Share View
return "MyShareEx";
}
}- ShareApplication should look like this
// your package you defined in ShareActivity
package com.sample1.share;
// import build config
import com.sample1.BuildConfig;
import com.alinz.parkerdan.shareextension.SharePackage;
import android.app.Application;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactPackage;
import java.util.Arrays;
import java.util.List;
public class ShareApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new SharePackage()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}- MainApplication should look like this
// your package you defined in ShareActivity
package com.sample1;
import android.app.Application;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.alinz.parkerdan.shareextension.SharePackage;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new SharePackage()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}- edit
android/app/src/main/AndroidMainfest.xmland add the newactivityright afterdevSettingActivity.
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
<activity
android:noHistory="true"
android:name=".share.ShareActivity"
android:configChanges="orientation"
android:label="@string/title_activity_share"
android:screenOrientation="portrait"
android:theme="@style/Theme.Share.Transparent" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
// for sharing links include
<data android:mimeType="text/plain" />
// for sharing photos include
<data android:mimeType="image/*" />
</intent-filter>
</activity>in this new activity I have used 2 variables @string/title_activity_share and @style/Theme.Share.Transparent. you can add those in res/values.
so in values/strings.xml
<resources>
...
<string name="title_activity_share">MyShareEx</string>
</resources>and in values/styles.xml
<resources>
...
<style name="Share.Window" parent="android:Theme">
<item name="android:windowEnterAnimation">@null</item>
<item name="android:windowExitAnimation">@null</item>
</style>
<style name="Theme.Share.Transparent" parent="android:Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowAnimationStyle">@style/Share.Window</item>
</style>
</resources>- now you should be able to compile the code without error.
if you need to add more packages to your share extension do not overrides
getPackages. instead overridegetMorePackagesmethod underShareExActivity.
so both share extension and main application are using the same code base, or same main.jsbundle file. So the trick to separate Share and Main App is registering 2 different Component entries with AppRegistry.registerComponent.
so in both iOS and android share extension we are telling react to load MyShareEx component from js.
so in index.ios.js and index.android.js we are writing the same code as
//index.android.js
import React from 'react'
import { AppRegistry } from 'react-native'
import App from './app.android'
import Share from './share.android'
AppRegistry.registerComponent('Sample1', () => App)
AppRegistry.registerComponent('MyShareEx', () => Share)//index.ios.js
import React from 'react'
import { AppRegistry } from 'react-native'
import App from './app.ios'
import Share from './share.ios'
AppRegistry.registerComponent('Sample1', () => App)
AppRegistry.registerComponent('MyShareEx', () => Share)so the app.ios and app.android.js refers to main app and share.ios.js and share.android.js refers to share extension.
data()is a function that returns a promise. Once the promise is resolved, you get two values,typeandvalue.
import ShareExtension from 'react-native-share-extension'
...
const { type, value } = await ShareExtension.data()close()
it simply close the share extension and return the touch event back to application that triggers the share.
because share extension in ios devices are separate containers and the do not have access to main app folder, you have to build the script twice and package it inside the share extension container. The easiest way of doing this is create a New Script Phase in Build Phases of your share extension and copy the following line
export NODE_BINARY=node
../node_modules/react-native/packager/react-native-xcode.shI have used react-native-modalbox module to handle the showing and hiding share extension which makes the experience more enjoyable for the user.
Cheers


















