GithubHelp home page GithubHelp logo

alinz / react-native-share-extension Goto Github PK

View Code? Open in Web Editor NEW
758.0 11.0 398.0 2.76 MB

react-native as an engine to drive share extension

License: MIT License

Java 52.65% Objective-C 18.86% JavaScript 1.81% Shell 26.68%

react-native-share-extension's Introduction

React Native Share Extension

This is a helper module which brings react native as an engine to drive share extension for your app.

Installation

Installation should be very easy by just installing it from npm.

npm install react-native-share-extension --save

Setup

The 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.

iOS

  • Click on your project's name
  • Click on + sign

  • Select Share Extension under iOS > Application Extension

  • Select a name for your new share extension, in my case I chose MyShareEx

  • Delete both ShareViewController.h and ShareViewController.m. make sure to click on the Move to Trash button during deletion.

  • Create a new file under your share extension group, in my case it was MyShareEx

  • Make sure that the type of that object is Objective-C File, e.g. for MyShareEx name it MyShareEx.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 on MainInterface.storyboard and replace the class field from ShareViewController to whatever you chose above (in my case MyShareEx)

  • Now it's time to add our library. Right click on the Libraries group and select Add 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 Sample1), then click on your extension name (in my case MyShareEx). After that click on Build Settings and search for Header Search Paths

  • Add the new path $(SRCROOT)/../node_modules/react-native-share-extension/ios with recursive selected

  • We need to add some linker flags as well, so search for Other Linker Flags and add -ObjC and -lc++

  • We also need to add all the static libraries such as React and React Native Share Extension. Select the General tab and under Linked frameworks and Libraries click on + and add all of the selected static binaries there

  • We need to modify the Info.plist inside the extension (e.g. MyShareEx/Info.plist) to make sure that our share extension can connect to internet. 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 to App Transport Security Settings to Info.plist

  • Now go back to your extension file (in my case MyShareEx.m) and paste the following code there being sure to substitute MyShareEx in all three places for whatever you chose above

If your project entry is index.js instead of index.ios.js then needs to replace @"index.ios" with @"index"

#import <Foundation/Foundation.h>
#import "ReactNativeShareExtension.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTLog.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;

  // Uncomment for console output in Xcode console for release mode on device:
  // RCTSetLogThreshold(RCTLogLevelInfo - 1);

  return rootView;
}

@end

Set the NSExtensionActivationRule key in your Info.plist

For the time being, this package only handles sharing of urls specifically from browsers. In order to tell the system to show your extension only when sharing a url, you must set the NSExtensionActivationRule key (under NSExtensionAttributes) in the share extension's Info.plist file as follows (this is also needed to pass Apple's reveiw):

<key>NSExtensionAttributes</key>
<dict>
  <key>NSExtensionActivationRule</key>
  <dict>
    <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
    <integer>1</integer>
  </dict>
</dict>

Note that while the above will prevent many apps from wrongly sharing using your extension, some apps (e.g., YouTube) will still allow sharing using your extension, which might cause your extension to crash. Check out this issue for details.

For reference about NSExtensionActivationRule checkout Apple's docs

  • Try to build the project, it should now build successfully!

Android

  • Edit android/settings.gradle 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.gradle and add the following line before the react section in dependencies
dependencies {
    ...
    compile project(':react-native-share-extension')
    compile "com.facebook.react:react-native:+"
}
  • Create a folder called share under your java project and create two files. Call them ShareActivity.java and ShareApplication.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 now 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
   public 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 now 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.xml and add the new activity right after devSettingActivity.
<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 any errors!

If you need to add more packages to your share extension, do not override getPackages, instead override the getMorePackages method under ShareExActivity.

Share Component

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.

In both the iOS and Android share extensions we are telling react to load the extension component (in my case MyShareEx) from js.

So in index.ios.js and index.android.js we are writing the same code:

//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) // TODO: Replace MyShareEx with my extension name
//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) // TODO: Replace MyShareEx with my extension name

So the app.ios and app.android.js refers to main app and share.ios.js and share.android.js refers to share extension.

Share Extension APIs

  • data() is a function that returns a promise. Once the promise is resolved, you get two values, type and value.
import ShareExtension from 'react-native-share-extension'
...

const { type, value } = await ShareExtension.data()
  • close()

Simply closes the share extension and returns the touch event back to application that triggered the share.

On iOS: Re-harvesting a shared image

If your share extension is being used to process shared images (be it to social media or processing the image for information), react-native-share-extension will provide a URL within value with the location of the image.

If you wish to pass this URL back down to Swift or Objective-C for whatever reason, you can use the following to convert the URL back into a UIImage:

func harvestImage(from imageURL: String) {
    if let imgData = FileManager.default.contents(atPath: imageURL) {
        if let img = UIImage(data: data){
        	// Process image..
        }
    }
}

or in Objective-C:

-(void)harvestImage:(NSString *)imageURL {
	NSFileManager *fileManager = [NSFileManager defaultManager];
	NSData *imgData = [fileManager contentsAtPath:imageURL];
	UIImage img = [UIImage imageWithData:imgData];
	// Process Image..
}

Test on Device without dev-server

Because a share extension in ios is treated as a separate container, they do not have access to main app folder. A resolution for this is that 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/scripts/react-native-xcode.sh

App and app extension bundles

The app and app extension bundles can be shared or separated. Separating bundles allows for a minimal footprint for both app and app extension.

plist key legend

BundleEntryFilename - react-native index or shared index filename.

BundleSkipped - Skips bundling when true.

BundleCopied - Copies bundle instead of building when true. (Note: Should be set as true for share extension plist only when bundles are shared.)

BundleForced - Forces bundling when true.

Shared bundles

The app extension target builds pre-loaded bundle and is copied to the app target.

app plist values

BundleEntryFilename = 'index.js'

BundleSkipped = true

BundleCopied = true

app target's "Bundle React Native code and images" phase

export NODE_BINARY=node
../bin/react-native-xcode.sh

appShareExtension plist values

BundleEntryFilename = 'index.js'

BundleForced = true

appShareExtension target's "Bundle React Native code and images" phase

cd ../
npm run cp-native-assets
cd ios/
export NODE_BINARY=node
../bin/react-native-xcode.sh

Separated bundles

The app extension and app targets build their own unique bundles.

NSNotificationCenter will kill app extensions that are unable to free memory resources when receiving low memory warnings. Also, shared bundles introduce library/pod dependencies that aren't needed by both apps. Configuring separate bundles via Xcode requires customizing react-native-xcode.sh; a quick example customization can be found in the bin directory. Update the path to the packager in both the app and app extension target's "Bundle React Native code and images" Build Phases.

Build time can be halved while debugging by disabling the bundle for whichever target you aren't debugging (app or app ex).

app plist values

BundleEntryFilename = 'index.js'

app target's "Bundle React Native code and images" phase

export NODE_BINARY=node
#export ENTRY_FILENAME=index
../bin/react-native-xcode.sh

appShareExtension plist values

BundleEntryFilename = 'share.index.js'

BundleForced = true

appShareExtension target's "Bundle React Native code and images" phase

cd ../
npm run cp-native-assets
cd ios/
export NODE_BINARY=node
../bin/react-native-xcode.sh

Open container app

Steps needed to open the host application from the share extension.

  1. Allow your app to be opened via URL Scheme - Learn more
  2. In xcode, select share extension and go to Build Settings and set Require Only App-Extension-Safe API to NO.

Then you can open your app from the share extension by calling openURL:

import ShareExtension from 'react-native-share-extension';

ShareExtension.openURL('sample://example/url');

Troubleshooting on iOS devices

Using the iOS Simulator and remote react-native debugger to develop the extension can hide issues that won't occur until testing on device. If you're experiencing issues running the extension on iOS devices, examine the Xcode console or device log for any obvious errors. If the Xcode console isn't receiving console output, ensure that the OS_ACTIVITY_MODE=disable environment var isn't enabled for the active scheme (see facebook/react-native#10027). OS_ACTIVITY_MODE will hide device logging in the Xcode console, so its use is only advisable for iOS Simulator. For release mode, in order to view console output and see all output in the syslog, uncomment the RCTSetLogThreshold(RCTLogLevelInfo - 1); statement in your MyShareEx class.

  1. If you're using react-native latest, error boundaries might help with JS errors. Another option is to catch render exceptions or test for errors, then render that output with something like a Text component. As long as your share app initializes, you should be able to see yellowbox/redbox errors. If you're not seeing them, you likely have an initialization issue.
  2. Disable bundling on the main target when debugging the extension target, it's not needed when you're not working with the main app.
  3. Enable breaking on exceptions. This is helpful if there are any exceptions in the extension itself; perhaps most useful if you've customized the native module.

Final note

I have used react-native-modalbox module to handle the showing and hiding share extension which makes the experience more enjoyable for the user.

Cheers

react-native-share-extension's People

Contributors

alinz avatar andrewhenderson avatar benjie avatar birkir avatar brenwarwcdg avatar isaachinman avatar itaibs avatar njt1982 avatar npomfret avatar parkerdan avatar runjuu avatar southernkept avatar sportnak avatar suhailsulu avatar thetekton avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-share-extension's Issues

Android Build error "method does not override or implement a method from a supertype"

Hi @alinz -- I tried to start a fresh new RN project and use the extension, but when I attempt to build it with 'react-native run-android', I keep getting the error:

:react-native-share-extension:compileReleaseJavaWithJavac
:react-native-share-extension:compileReleaseJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.).
/NEW_RN_APP/node_modules/react-native-share-extension/android/src/main/java/com/github/alinz/reactNativeShareExtension/ShareExActivity.java:78: error: method does not override or implement a method from a supertype
    @Override
    ^
1 error
:react-native-share-extension:compileReleaseJavaWithJavac FAILED

Are you familiar with this error or how I might troubleshoot it? Thanks!

Help needed making Sample1 example works on Android

Hi,

I tried your example on Android and I did not succeed to make it work.
I have:

  • "react": "15.3.1",
  • "react-native": "0.32.0",

When I try to share either an url or an image, in the share.android.js, in componentDidMount function, ShareExtension is not defined. I got this error :

errrr TypeError: Cannot read property 'data' of undefined(…)

Do you know how to solve this error?

Updates/corrections to README.md

First off, thanks for sharing this code -- I really needed it! As a relative newbie to RN, iOS and Android dev I followed your readme quite closely and noticed two corrections:

we need to add some flags as well, so search for Other Linker Flags and add -Objc and -lc++

-Objc should be properly cased to capital O and capital C: -ObjC (good thing there was a screenshot, but my eagerness to blindly copy/paste sent me down a debugging rabbit-hole for a day or so :) You only get an error indicating there's a problem if you run in Xcode with the extension as the target -- if you run with the app as the target, it fails silently.

Second, minor correction, in your code snippet for MyShareEx.m:

  • now go back to MyShareEx.m and paste the following code there.
...
@interface MyShareEx : ReactNativeShareExtension
@end
@implementation MyShareEx
- (UIView*) shareView {
..

need to include 'RCT_EXPORT_MODULE();' in between '@implementation MyShareEx' and
'- (UIView*) shareView {' to read:

...
@interface MyShareEx : ReactNativeShareExtension
@end

@implementation MyShareEx
RCT_EXPORT_MODULE();
- (UIView*) shareView {
...

RCT_EXPORT_MODULE(); is in the actual file, but again, if someone copy/pasted from the readme, they would have missed it...luckily this was not a showstopper and did not break the module.

Android sometimes getting empty strings

On Android, every once in awhile the share extension send back to the js side a {type: '', value: ''} object.

From debugging this, it seems this happens for two possible reasons that both occur:

  1. getCurrentActivity can return null

  2. Sometimes the android intent type is null (Intent.getType()), even when the same share action is performed (sharing from chrome).

Any ideas?

On iOS: Native module cannot be null

Hi,

We're experiencing an issue with our iOS share extension (android works perfectly) where when we try to use the extension it seems that nothing happens. When checking the system logs we get an error saying "Native module cannot be null".

After that it says: Module AppRegistry is not a registered callable module (calling runApplication)

We are linking all of the libraries, as far as I can tell. Moreover, everything already worked fine before.

Any idea what might cause such an error?

opens host app instead of share extension

I've got everything working on the simulator, but when trying to test it on a physical device(with no dev server whatsoever), instead of opening the share extension, it opens up the host application.

Before this, it didn't opened anything and then i remembered to add the https://github.com/alinz/react-native-share-extension#test-on-device-without-dev-server.
Should this script be added to both host app and extension or just the extension?

currenty package.json:

"react-native": "0.42.3"
"react-native-share-extension": "^1.1.1"

Thanks in advance!

Opening video file freezes application

Environment
react-native: 0.45.1
release version
android: 7.0
ios: 11.1

Hi the ShareExtension has been working great for images, text & links, but seems to crash my application when opening a video. This happens on both iOS and Android, and it seems to stall on this line:

const { type, value } = await ShareExtension.data();

Any help would be greatly appreciated thanks!

Help on getting share working on iOS

Sorry, this isn't an issue, but I've been trying for hours now. I've got the sample project working, but when I try and integrate this to my own it fails.

The problem is when I hit the share button in Safari, and then select my application, the modal popup doesn't appear. In fact, Safari becomes completely unresponsive. The only thing I can see is some activity happening in my node log, but nothing appears on screen. Safari doesn't become responsive again until I restart my app, even just killing my app leaves Safari in a broken state.

I can't even debug it - Chrome refuses to allow any breakpoints in the Share.ios.js file. And any breakpoints I add to my Share xCode project never get hit.

Any suggestions on how I can debug what's going on?

Image sharing on iOS returns no data

Back in September, @parkerdan kindly contributed a PR adding image support, which was merged by @alinz.

After testing this on both iOS 10.1 and and 9.3, it seems that data() doesn't return anything when you share an image from the Photos app. Sharing a URL from Safari works fine however.

I know next to nothing about coding in Objective C. Looking through ios/ReactNativeShareExtension.m, I wonder whether the url variable isn't working as expected before it's passed into the callback, or if there's something else at play?:

}else if (imageProvider){
[imageProvider loadItemForTypeIdentifier:IMAGE_IDENTIFIER options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) {
NSURL *url = (NSURL *)item;
if(callback) {
callback(url,[[[url absoluteString] pathExtension] lowercaseString] ,nil);
}
}];

Is there something else that needs to be enabled first for image sharing to work?

Possible docs problem

I think the section about Linked frameworks and Libraries could be improved (maybe!). It says to click on + and add all of the selected static binaries there. I did this but got a few compile errors. My project has loads of native libraries included and I think they were the cause of the problem. I removed them all and just kept the ones with names beginning with libRCT... and libReact and the compile was much happier.

Crash in production...

@alinz Hi man, sorry to bother you again.

Do you know or, have you heard someone talking about the crash when using Fastlane? I have added the script to build local on my device... at this point, everything is okay but, when I'm using Fastlane to deploy my app to the testers, the extension is not opening =l

What is the best way to debug it?

Ps. Odin, help me! 🙏 😂

modal show on iOS only one time

Hello, I set up according to your steps, and then there was a very strange phenomenon,the modal box on ios can only show one time, the first time is normal, but after I call "ShareExtension.close()" function,evoke ShareExtension once again,only MyShareEx.m’s view appears the modal box no longer appears,
I have set “rootView.backgroundColor = [UIColor redColor];”,this is screenshots,
59691022-c8f9-4bad-b9e1-29e8040b0491
the first time, and the second time
15acc44b-7498-42b3-8081-1c045f78603d
Very strange, do you know why?
my english is poor, I do not know if you have understand what I mean。

Question on communication with share.ios.js and app.ios.js

Actually, this isn't an issue, just wonder how you communicate with share.ios.js and app.ios.js. I want to pass the value to the app.ios.js when data received in share.ios.js.

I'm new to RN, have tried events (Emitter) and global variables but neither works.
I think these components have separate JS environment ?

Sharing Photos / Sharing from Library Only

Hello! Thank you so much for doing such an awesome job with this extension.

Is there a way to allow sharing screenshots only and hide the extension for any other type of shares?

Also, I've managed to install the extension correctly but the Extension doesn't show up when I try to share an image from the Photo Library.

Thanks!

Sharing an image

So, sharing URLs from Safari or any in-app browser works really well!

How about other forms of content? Images, for example? I'm trying with an image from the simulator but ShareExtension.data() appears to just hang... is there any point where I can enable some form of debugging to try and work out what's going on within the ShareExtension class?

Debug menu doesn't show

Hi - thanks for creating this project. I have it all up and running, but I can't get the regular react native debug menu to show, pressing CMD+D or initiating the shake gesture doesn't launch the menu, the one where you can turn on Live Reload, turn on remote JS debugging.

Is there some way to make this appear? I want to be able to inspect elements and remote debug the react native view when it is loaded in the extension.

Thanks.

Memory limit issue on iOS

Thank you very much for this great library!

Right now i have only one issue. When i open and close extension, memory consumption only increase (double every time). After some reopens it crashes, because strict memory limits for extensions on iOS.
It's looks like when extension is closed it not freeing memory.

Maybe you have some ideas, how to force free memory?

Cannot resolve contact data on iOS

Hi All,

This awesome module is working greatly on URL-based content sharing. However, when I try sharing contacts (Contact -> pick up a contact -> share this contact), there is no url giving out. How do we suppose to receive contact data from sharing extension?

Thanks!

iOS, AppStore share

image

When i try to share from App Store, extension crashes with this error.
Very strange, because AppStore probably not sharing an image, but link.

Compile warning: Embedded binary's NSExtensionActivationRule is TRUEPREDICATE

I've just tried to install this for the first time. When I compiled I saw this worrying warning:

warning: Embedded binary's NSExtensionActivationRule is TRUEPREDICATE. Before you submit your containing app to the App Store, be sure to replace all uses of TRUEPREDICATE with specific predicate statements or NSExtensionActivationRule keys. If any extensions in your containing app include TRUEPREDICATE, the app will be rejected.

Not sure what it means though, or how to get rid of it but it looks important. Any ideas?

prod crash

My app is crashing, quite randomly when the share extension starts. It works in dev/debug mode. But when I launch it from test flight it crashes. Not on all devices... can't spot a pattern but I've managed to find the following error. Anyone else seeing this?

2017-05-12 21:55:01.746109+0100 MobileSafari[19259:4285864] [core] SLRemoteComposeViewController: (this may be harmless) viewServiceDidTerminateWithError: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}
2017-05-12 21:55:01.747782+0100 MobileSafari[19259:4285864] viewServiceDidTerminateWithError:: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}
Program ended with exit code: 02017-05-12 21:55:05.829921+0100 MobileSafari[19259:4298270] libMobileGestalt MobileGestaltSupport.m:153: pid 19259 (MobileSafari) does not have sandbox access for frZQaeyWLUvLjeuEK43hmg and IS NOT appropriately entitled
2017-05-12 21:55:05.829960+0100 MobileSafari[19259:4298270] libMobileGestalt MobileGestalt.c:550: no access to InverseDeviceID (see <rdar://problem/11744455>)

just a blank screen?

Hi @alinz and thank you for making this very promising module. however i have not been able to follow the instructions successfully. I can build the app but when i try to share from Safari it just shows a blank screen:
image

i know you might be thinking that i didnt link the class but I did:

image

any other ideas why this might happen?

also i have no idea how you add the modal, you hint at that in your README and you give some code in the issues but i dont know how to link from that to XCode.

Error after updating to RN 0.47.2?

Hi, i was this library working fine but some day (i think after upgrade React Native) this broke.

XCode build okey but when i share something from safari, camera roll or somewhere y have this error in console.

(myapp.debug.share) <Warning>: Unknown key for Boolean: EnableTransactions

(myapp.debug.share) <Warning>: Unknown key for Boolean: EnablePressuredExit

(com.apple.DictionaryServiceHelper) <Warning>: Unknown key for Boolean: EnableTransactions

(com.apple.DictionaryServiceHelper) <Warning>: Unknown key for Boolean: EnablePressuredExit

(com.apple.StreamingUnzipService) <Warning>: Unknown key for Boolean: EnableTransactions

(com.apple.StreamingUnzipService) <Warning>: Unknown key for Boolean: EnablePressuredExit

(com.apple.uifoundation-bundle-helper) <Warning>: Unknown key for Boolean: EnableTransactions

(com.apple.uifoundation-bundle-helper) <Warning>: Unknown key for Boolean: EnablePressuredExit

(myapp..debug.share[36327]) <Error>: assertion failed: 16G29: launchd_sim + 63487 [4F755FB1-4156-3577-BEB8-3FD0A54C6323]: 0x16

Have you got some clue?

regards!

Marcelo.

Exception: Module AppRegistry is not a registered callable module (calling runApplication)

Hi everyone,

i am having trouble setting up the module for my iOS app.

I added a Share Extension to my existing app project through Xcode by applying all the steps from the Readme. I ended up with a "index.ios.js" file where i added the additional registerComponent() call for the extension (imported as "Share", i used the share.ios.js from the example). The Extension itself is called "ShareExt" in the "ShareExt.m"-Obj-C-file, my main App is called "QRSticker" and still works when started with react-native run-ios.

Here are the parts i added to my index.ios.js file:

AppRegistry.registerComponent('QRSticker', () => QRSticker);
AppRegistry.registerComponent('ShareExt', () => Share);

The main app still works fine as it has for a while. The extension however does not seem to be working. The extension itself is visible from the share menu in the simulator, but as soon as i touch the icon, the following error message occurs:

Mar 24 15:20:14 MacBook-Pro pkd[15852] : Use of NSTruePredicate is forbidden: TRUEPREDICATE
Mar 24 15:20:18 MacBook-Pro com.apple.WebKit.Networking[23418] : [] nw_endpoint_handler_add_write_request [14.1 37.252.172.53:443 failed socket-flow (satisfied)] cannot accept write requests
Mar 24 15:20:18 MacBook-Pro com.apple.WebKit.Networking[23418] : [] __tcp_connection_write_eof_block_invoke Write close callback received error: [22] Invalid argument
Mar 24 15:20:26 MacBook-Pro logd[15811] : metadata shared cached uuid is null (using logd's shared cache info) ShareExt (23420)
Mar 24 15:20:26 MacBook-Pro logd[15811] : Failed to harvest strings for pathless uuid '00000000-0000-0000-0000-000000000000'
Mar 24 15:20:26 MacBook-Pro com.apple.CoreSimulator.SimDevice.29252BE3-88F8-42FE-B09E-D6681A92EA79.launchd_sim[15800] (com.apple.imfoundation.IMRemoteURLConnectionAgent) : Unknown key for integer: _DirtyJetsamMemoryLimit
Mar 24 15:20:26 MacBook-Pro ShareExt[23420] : Failed to inherit CoreMedia permissions from 23417: (null)
Mar 24 15:20:26 MacBook-Pro ShareExt[23420] : Initializing <RCTBatchedBridge: 0x6000001a41a0> (parent: <RCTBridge: 0x6080000d47b0>, executor: RCTJSCExecutor)
Mar 24 15:20:26 MacBook-Pro backboardd[15818] : [Common] Unable to bootstrap_look_up port with name in.timo.ios.QRSticker.ShareExt.gsEvents: unknown error code (1102)
Mar 24 15:20:26 MacBook-Pro SpringBoard[15817] : [KeyboardArbiter] HW kbd: Failed to set in.timo.ios.QRSticker.ShareExt as keyboard focus
Mar 24 15:20:26 MacBook-Pro SpringBoard[15817] : [KeyboardArbiter] [_UIKeyboardArbiter] Rejecting attach for <_UIKeyboardArbiterHandle: 0x6180006f4280; PID 23417: com.apple.mobilesafari <com.apple.mobilesafari>; hosting PIDs {(
23420
)}; level 0.000000; active NO [wants YES]; suppression 0> (currently (null))
Mar 24 15:20:26 MacBook-Pro ShareExt[23420] : [] __nw_connection_get_connected_socket_block_invoke 4 Connection has no connected handler
Mar 24 15:20:26 MacBook-Pro ShareExt[23420] : Sending websocketFailed with no listeners registered.
Mar 24 15:20:26 MacBook-Pro ShareExt[23420] : undefined is not an object (evaluating 'RNFSManager.RNFSFileTypeRegular')
Mar 24 15:20:26 MacBook-Pro ShareExt[23420] : Unhandled JS Exception: undefined is not an object (evaluating 'RNFSManager.RNFSFileTypeRegular')
Mar 24 15:20:26 MacBook-Pro ShareExt[23420] : Running application ShareExt ({
initialProps = {
};
rootTag = 1;
})
Mar 24 15:20:26 MacBook-Pro ShareExt[23420] : Module AppRegistry is not a registered callable module (calling runApplication)
Mar 24 15:20:26 MacBook-Pro ShareExt[23420] : Unhandled JS Exception: Module AppRegistry is not a registered callable module (calling runApplication)
Mar 24 15:20:27 MacBook-Pro ShareExt[23420] : -[NSNull integerValue]: unrecognized selector sent to instance 0x10f86c130
Mar 24 15:20:27 MacBook-Pro ShareExt[23420] : Exception '-[NSNull integerValue]: unrecognized selector sent to instance 0x10f86c130' was thrown while invoking updateExceptionMessage on target ExceptionsManager with params (
"undefined is not an object (evaluating 'RNFSManager.RNFSFileTypeRegular')",

The error that caught my attention is "Unhandled JS Exception: Module AppRegistry is not a registered callable module (calling runApplication)". That doesn't seem to be right. Since the Xcode-Part of the setup seems to work, i guess my React setup is the problem.

I am launching the app with react-native run-ios, go back to the Homescreen and then try to launch the Share Extension from the Mobile Safari.

Can someone point me in the right direction? :)

  • Timo

Class won't launch react-native view

Hi there, great project.

I've added it to a react-native project and it works without issues on android.
Trying to use it in the iOS part, I have some issues starting the shared component.

The rootView gets inserted and i can change its background color, but it won't launch the react-native view.

I tried to reduce my index.ios.js to use a minimal <View> with some style, but nothing gets called inside the js module.

The xcode output complains that No bundle URL present.
Does anyone have any suggestions on what i could do to fix this issue?
The project is using latest versions of react-native and this addon.

Full log
2017-04-04 13:11:19.191 [info][tid:main][RCTBatchedBridge.m:72] Initializing <RCTBatchedBridge: 0x1741b5d20> (parent: <RCTBridge: 0x1700de300>, executor: RCTJSCExecutor)
2017-04-04 13:11:19.196066 freiraumShare[5143:2801405] Initializing <RCTBatchedBridge: 0x1741b5d20> (parent: <RCTBridge: 0x1700de300>, executor: RCTJSCExecutor)
2017-04-04 13:11:19.197 [warn][tid:main][RCTBatchedBridge.m:110] Failed to load source: Error Domain=RCTErrorDomain Code=0 "No bundle URL present.

Make sure you're running a packager server or have included a .jsbundle file in your application bundle." UserInfo={NSLocalizedDescription=No bundle URL present.

Make sure you're running a packager server or have included a .jsbundle file in your application bundle.}
2017-04-04 13:11:19.196755 freiraumShare[5143:2801405] Failed to load source: Error Domain=RCTErrorDomain Code=0 "No bundle URL present.

Make sure you're running a packager server or have included a .jsbundle file in your application bundle." UserInfo={NSLocalizedDescription=No bundle URL present.

Make sure you're running a packager server or have included a .jsbundle file in your application bundle.}

Usage problem with wix/react-native-navigation on Android

Hello, I've sucessfully used both libs together on [email protected] but after upgrading to [email protected], I encountered a new problem that I didn't have before:

To perform the upgrade I created a new react-native project in a separared directory, moved in the source files I wrote and reapplied all the manual integrations one by one (namely: rn-navigation, rn-share-extension and rn-swiss-knife), so we can assume there are no stale settings somewhere that didn't get properly updated. Also I used [email protected] with [email protected] and [email protected] with [email protected]

Now the problem is as follows:
For reasons that I don't fully understand, react-native-navigation changes the way the app is loaded by skipping the AppRegistry.registerComponent step and while before it didn't cause any problem, now "forcing" the execution of the main application makes the share extension crash.

myapp/MainActivity.java

import com.reactnativenavigation.controllers.SplashActivity;

public class MainActivity extends SplashActivity {
	
}

index.android.js

import { AppRegistry } from 'react-native'
import App from './src/app'
import Share from './src/share'

AppRegistry.registerComponent('MyShare', () => Share)

let app = new App()

The App instance, after some setup, calls Navigation.startSingleScreenApp and the main application starts. Without that line, the share extension works perfectly but the main application doesn't load (I get a white screen), but, with it, the share extension crashes.

On iOS this doesn't cause any problem even with the new version of react-native, it's something on android that has changed.
EDIT: Apparently it keeps working on iOS when building in debug mode, when using the release scheme I get the same error and also in this case the "fix" is to delete the new App line.

Is there any way of checking "who" whats to call "what" and only instantiate App when the user wants the main application? Or anything else that can be done to obtain the previous convenient behavior?

For reference:
myapp/MainApplication.java

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;
import com.reactnativenavigation.NavigationApplication;
import com.alinz.parkerdan.shareextension.SharePackage;
import com.github.alinz.rnsk.RNSKPackage;

public class MainApplication extends NavigationApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new SharePackage(),
          new RNSKPackage()
      );
    }
  };

  @Override
  public boolean isDebug() {
     // Make sure you are using BuildConfig from your own application
    return BuildConfig.DEBUG;
  }

  @Override
  public List<ReactPackage> createAdditionalReactPackages() {
     // Add the packages you require here.
     // No need to add RnnPackage and MainReactPackage
    return Arrays.<ReactPackage>asList(
          new RNSKPackage()
      );
  }

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

#import "RCTBridgeModule.h" file not found

I'm receiving this error. What went wrong?

Take a look how is my Header Search Paths. It's a strange error because on my friend's computer it's working well.

f_j052d5

Thank you.

Crash when sharing from the iOS 11 screenshot editor.

The following project shows an example of a app that utilizes react-native-share-extension to the simplest level: https://github.com/bluey31/ShareTest11

When the share extension is triggered from Photos, for example, the share extension persists and can be interacted with. Although, when the share extension is triggered from the iOS 11 screenshot editor (that is presented in iOS 11 when a screenshot is taken) the share extension crashes due to thanks from the line const { type, value } = await ShareExtension.data() (#60 ShareTest11Ext.js).

I believe the way you harvest the photo is having trouble dealing with the fact the image is mid-edit...hope this helps.

Brendon

Crashing on iOS when sharing from specific apps

Hi!
First of all, thanks for the amazing package. Super helpful for our project.

I have everything set up and working on both android and iPhone. On android everything works perfectly and same is true for iPhone when sharing from chrome/safari.

But when trying to share from YouTube (and some other apps as well, e.g., notes) the share extension crashes with the next exception (I found on the console logs):

Exception '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]' was thrown while invoking data on target ReactNativeShareExtension with params (
6,
7
)

I have no idea what to do about this. Would appreciate any input :).

Thanks!

Import errors on build (iOS)

Hi,

I'm running into several import issues, while trying to create a build for iOS, for example: React/RCTBridgeModule.h file not found
I've tried everything from react-native 0.37.0 - latest.

Is there a version stack of react and react native you usually use for this app?

Thanks in advance!

How to Get Extension to Show up In Safari Share

Hey great work Alinz. I followed all the instructions for installation and the build succeeded. However I'm having trouble seeing the extension show up when I press "Share" on Safari on the iOS Simulator. I press "More" and see the only default apps of Facebook, Twitter, and Reminders. How do I make my extension show up there? Is there a particular file which I should double check to make sure is edited?

Crashing on iOS by FB Bolts lib

Hello, i am having a trouble with the share extension and other libs i hope to have an answer here.
When I open the extension it fails because there are missing libraries (the ones I use in the main app, such as google-sign-in, FBSDK, etc). If i add the missing libraries to the extension target,
Xcode will not let me build because "Shared Application" (used in Facebook Bolts lib) is not available in the extension.

log-ios if not include lib on target:

<Warning>: Warning: Native component for "RCTFBLikeView" does not exist
<Warning>: Warning: Native component for "RCTFBLoginButton" does not exist
<Warning>: Warning: Native component for "RCTFBSendButton" does not exist
<Warning>: Warning: Native component for "RCTFBShareButton" does not exist
<Error>: Native module cannot be null.
<Critical>: Unhandled JS Exception: Native module cannot be null.
<Notice>: Running application TaringaShare ({
	    initialProps =     {
	    };
	    rootTag = 1;
	})
<Error>: Module AppRegistry is not a registered callable module (calling runApplication)
<Critical>: Unhandled JS Exception: Module AppRegistry is not a registered callable module (calling runApplication)

Xcode error if include lib:

/path-to-ios-project/Pods/Bolts/Bolts/iOS/BFAppLinkReturnToRefererView.m:143:49: 'sharedApplication' is unavailable: not available on iOS (App Extension) - Use view controller based solutions where appropriate instead.

I'm doing something wrong?

Thanks!!

Published version is out of date (1.1.1)

Please publish the latest code to npm. The current version is v1.1.1 which is over 6 months old and doesn't include several changes such as plain text share. Thanks!!

=)

Share media files with main application

Thank you for this great module. After some problems in the beginning I got it running very well!

Is there a way to share a media file (photo/video) with the main application? I set app groups for the extension and the application. Within the extension I added react-native-fs to get access to the filesystem. But I have no idea how to save the image to the shared folder and open it within my main application.

A workaround could be using your RNSKBucket and save the image as a base64 string, saving it while opening the app by writing it to the cache folder and clearing the bucket afterwards. But this seems a little hacky.

I am not really into Objective-C programming and I was wondering how to achieve this with react native, any other ideas?

Crashing when closing extension on Android

When running the following code in the Share Extension on Android:

close = () => { ShareExtension.close() }
...
render() {
...
<TouchableOpacity onPress={this.close}>
...

The app crashes with the error message:

undefined is not an object (evaluating '_reactNative.nativeModules.ReactNativeShareExtension.close')

Dont show modal on iOS

Hi, thanks for this component.

On iOS i think all its fine configured but when i press on share to MyAppShareEx, nothing happen. It dont show any popup.

Some idea? If need some code of my config ask me and i will post it.

Thanks!

share image from chrome web page

get value file://null

and

uri.toString() is content://com.android.chrome.FileProvider/images/screenshot/1491884783726318722338.jpg

Shared bundles issue

Hi. I need solution where my extension and main app will share same storage (use AsyncStorage). Guess shared bundles will help me achieve that?
Following the steps i stop on two issues:

  1. cant find appShareExtension target's "Bundle React Native code and images" phase
  2. what is cp-native-assets? script or?
    Thanks in advance

Cannot close extension iOS

Couple of issues:

  • My extension will not close once it is open. I doesn't appear that the native close method is being called at all, but I could be wrong about that.
  • The background color is completely white, not transparent like in the example, but I've implemented the code like in the example.

I'm on React Native 0.5+
Thanks

Limited to fetching url of the website.

First of all brilliant work. I really found my starting point on this repo, I need to extend the functionality to support other item-types/intent-types in my share extension. any idea how to go about it? because I got your demo working in a heartbeat but then I saw that the type 'public.url' is hard coded in the native side of the iOS. And I don't have much knowledge on Android about this.

I am trying to get json data out of the webpage after being processed by my custom javascript file, as we do in iOS for safari share extension. please help me on this and I am also ready to contribute my time in developing this repo.

Waiting for your response.. :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.