diff --git a/README.md b/README.md
index dd05d506..ceee7f38 100644
--- a/README.md
+++ b/README.md
@@ -154,6 +154,33 @@ However, what exactly gets shared, depends on the application the user chooses t
- Facebook iOS: message, image (other filetypes are not supported), link. Beware that since a Fb update in April 2015 sharing a prefilled message is no longer possible when the Fb app is installed (like Android), see #344. Alternative: use `shareViaFacebookWithPasteMessageHint`.
### Using the share sheet
+Since versin 5.1.0 (for iOS and Android) it's recommended to use `shareWithOptions` as it's the most feature rich way to share stuff cross-platform.
+
+It will also tell you if sharing to an app completed and which app that was (if that app plays nice, that is).
+
+```js
+// this is the complete list of currently supported params you can pass to the plugin (all optional)
+var options = {
+ message: 'share this', // not supported on some apps (Facebook, Instagram)
+ subject: 'the subject', // fi. for email
+ files: ['', ''], // an array of filenames either locally or remotely
+ url: 'https://www.website.com/foo/#bar?a=b',
+ chooserTitle: 'Pick an app' // Android only, you can override the default share sheet title
+}
+
+var onSuccess = function(result) {
+ console.log("Share completed? " + result.completed); // On Android apps mostly return false even while it's true
+ console.log("Shared to app: " + result.app); // On Android result.app is currently empty. On iOS it's empty when sharing is cancelled (result.completed=false)
+}
+
+var onError = function(msg) {
+ console.log("Sharing failed with message: " + msg);
+}
+
+window.plugins.socialsharing.shareWithOptions(options, onSuccess, onError);
+```
+
+#### You can still use the older `share` method as well
Here are some examples you can copy-paste to test the various combinations:
```html
diff --git a/package.json b/package.json
index 0f77768d..b339f447 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-x-socialsharing",
- "version": "5.0.12",
+ "version": "5.1.0",
"description": "Share text, images (and other files), or a link via the native sharing widget of your device. Android is fully supported, as well as iOS 6 and up. WP8 has somewhat limited support.",
"cordova": {
"id": "cordova-plugin-x-socialsharing",
diff --git a/plugin.xml b/plugin.xml
index cecdba64..8924b041 100755
--- a/plugin.xml
+++ b/plugin.xml
@@ -2,7 +2,7 @@
+ version="5.1.0">
SocialSharing
diff --git a/src/android/nl/xservices/plugins/SocialSharing.java b/src/android/nl/xservices/plugins/SocialSharing.java
index 0ffb4ac3..8b843370 100644
--- a/src/android/nl/xservices/plugins/SocialSharing.java
+++ b/src/android/nl/xservices/plugins/SocialSharing.java
@@ -36,6 +36,7 @@ public class SocialSharing extends CordovaPlugin {
private static final String ACTION_AVAILABLE_EVENT = "available";
private static final String ACTION_SHARE_EVENT = "share";
+ private static final String ACTION_SHARE_WITH_OPTIONS_EVENT = "shareWithOptions";
private static final String ACTION_CAN_SHARE_VIA = "canShareVia";
private static final String ACTION_CAN_SHARE_VIA_EMAIL = "canShareViaEmail";
private static final String ACTION_SHARE_VIA = "shareVia";
@@ -47,9 +48,10 @@ public class SocialSharing extends CordovaPlugin {
private static final String ACTION_SHARE_VIA_SMS_EVENT = "shareViaSMS";
private static final String ACTION_SHARE_VIA_EMAIL_EVENT = "shareViaEmail";
- private static final int ACTIVITY_CODE_SEND = 1;
- private static final int ACTIVITY_CODE_SENDVIAEMAIL = 2;
- private static final int ACTIVITY_CODE_SENDVIAWHATSAPP = 3;
+ private static final int ACTIVITY_CODE_SEND__BOOLRESULT = 1;
+ private static final int ACTIVITY_CODE_SEND__OBJECT = 2;
+ private static final int ACTIVITY_CODE_SENDVIAEMAIL = 3;
+ private static final int ACTIVITY_CODE_SENDVIAWHATSAPP = 4;
private CallbackContext _callbackContext;
@@ -71,27 +73,29 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
return true;
} else if (ACTION_SHARE_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), null, false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), null, null, false, true);
+ } else if (ACTION_SHARE_WITH_OPTIONS_EVENT.equals(action)) {
+ return shareWithOptions(callbackContext, args.getJSONObject(0));
} else if (ACTION_SHARE_VIA_TWITTER_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "twitter", false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "twitter", null, false, true);
} else if (ACTION_SHARE_VIA_FACEBOOK_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", null, false, true);
} else if (ACTION_SHARE_VIA_FACEBOOK_WITH_PASTEMESSAGEHINT.equals(action)) {
this.pasteMessage = args.getString(4);
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", null, false, true);
} else if (ACTION_SHARE_VIA_WHATSAPP_EVENT.equals(action)) {
if (notEmpty(args.getString(4))) {
return shareViaWhatsAppDirectly(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4));
} else {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "whatsapp", false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "whatsapp", null, false, true);
}
} else if (ACTION_SHARE_VIA_INSTAGRAM_EVENT.equals(action)) {
if (notEmpty(args.getString(0))) {
copyHintToClipboard(args.getString(0), "Instagram paste message");
}
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "instagram", false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "instagram", null, false, true);
} else if (ACTION_CAN_SHARE_VIA.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), true);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), null, true, true);
} else if (ACTION_CAN_SHARE_VIA_EMAIL.equals(action)) {
if (isEmailAvailable()) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
@@ -101,7 +105,7 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
return false;
}
} else if (ACTION_SHARE_VIA.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), null, false, true);
} else if (ACTION_SHARE_VIA_SMS_EVENT.equals(action)) {
return invokeSMSIntent(callbackContext, args.getJSONObject(0), args.getString(1));
} else if (ACTION_SHARE_VIA_EMAIL_EVENT.equals(action)) {
@@ -173,9 +177,9 @@ public void run() {
// as an experiment for #300 we're explicitly running it on the ui thread here
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
- cordova.startActivityForResult(plugin, Intent.createChooser(draft, "Choose Email App"), ACTIVITY_CODE_SENDVIAEMAIL);
- }
- });
+ cordova.startActivityForResult(plugin, Intent.createChooser(draft, "Choose Email App"), ACTIVITY_CODE_SENDVIAEMAIL);
+ }
+ });
}
});
@@ -194,7 +198,30 @@ private String getDownloadDir() throws IOException {
}
}
- private boolean doSendIntent(final CallbackContext callbackContext, final String msg, final String subject, final JSONArray files, final String url, final String appPackageName, final boolean peek) {
+ private boolean shareWithOptions(CallbackContext callbackContext, JSONObject jsonObject) {
+ return doSendIntent(
+ callbackContext,
+ jsonObject.optString("message", null),
+ jsonObject.optString("subject", null),
+ jsonObject.optJSONArray("files") == null ? new JSONArray() : jsonObject.optJSONArray("files"),
+ jsonObject.optString("url", null),
+ null,
+ jsonObject.optString("chooserTitle", null),
+ false,
+ false
+ );
+ }
+
+ private boolean doSendIntent(
+ final CallbackContext callbackContext,
+ final String msg,
+ final String subject,
+ final JSONArray files,
+ final String url,
+ final String appPackageName,
+ final String chooserTitle,
+ final boolean peek,
+ final boolean boolResult) {
final CordovaInterface mycordova = cordova;
final CordovaPlugin plugin = this;
@@ -305,12 +332,12 @@ public void run() {
// as an experiment for #300 we're explicitly running it on the ui thread here
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
- mycordova.startActivityForResult(plugin, Intent.createChooser(sendIntent, null), ACTIVITY_CODE_SEND);
+ mycordova.startActivityForResult(plugin, Intent.createChooser(sendIntent, chooserTitle), boolResult ? ACTIVITY_CODE_SEND__BOOLRESULT : ACTIVITY_CODE_SEND__OBJECT);
}
});
+ }
}
}
- }
});
return true;
}
@@ -554,10 +581,26 @@ private JSONArray getShareActivities(List activityList) {
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (_callbackContext != null) {
- if (ACTIVITY_CODE_SENDVIAEMAIL == requestCode) {
- _callbackContext.success();
- } else {
- _callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, resultCode == Activity.RESULT_OK));
+ switch (requestCode) {
+ case ACTIVITY_CODE_SEND__BOOLRESULT:
+ _callbackContext.sendPluginResult(new PluginResult(
+ PluginResult.Status.OK,
+ resultCode == Activity.RESULT_OK));
+ break;
+ case ACTIVITY_CODE_SEND__OBJECT:
+ JSONObject json = new JSONObject();
+ try {
+ json.put("completed", resultCode == Activity.RESULT_OK);
+ json.put("app", ""); // we need a completely different approach if we want to support this on Android. Idea: https://clickclickclack.wordpress.com/2012/01/03/intercepting-androids-action_send-intents/
+ _callbackContext.sendPluginResult(new PluginResult(
+ PluginResult.Status.OK,
+ json));
+ } catch (JSONException e) {
+ _callbackContext.error(e.getMessage());
+ }
+ break;
+ default:
+ _callbackContext.success();
}
}
}
diff --git a/src/ios/SocialSharing.h b/src/ios/SocialSharing.h
index 399cd239..0c731450 100644
--- a/src/ios/SocialSharing.h
+++ b/src/ios/SocialSharing.h
@@ -11,6 +11,7 @@
- (void)available:(CDVInvokedUrlCommand*)command;
- (void)setIPadPopupCoordinates:(CDVInvokedUrlCommand*)command;
- (void)share:(CDVInvokedUrlCommand*)command;
+- (void)shareWithOptions:(CDVInvokedUrlCommand*)command;
- (void)canShareVia:(CDVInvokedUrlCommand*)command;
- (void)canShareViaEmail:(CDVInvokedUrlCommand*)command;
- (void)shareVia:(CDVInvokedUrlCommand*)command;
diff --git a/src/ios/SocialSharing.m b/src/ios/SocialSharing.m
index 31146a45..9042ea25 100644
--- a/src/ios/SocialSharing.m
+++ b/src/ios/SocialSharing.m
@@ -7,6 +7,11 @@
#import
#import
+static NSString *const kShareOptionMessage = @"message";
+static NSString *const kShareOptionSubject = @"subject";
+static NSString *const kShareOptionFiles = @"files";
+static NSString *const kShareOptionUrl = @"url";
+
@implementation SocialSharing {
UIPopoverController *_popover;
NSString *_popupCoordinates;
@@ -52,6 +57,26 @@ - (CGRect)getPopupRectFromIPadPopupCoordinates:(NSArray*)comps {
}
- (void)share:(CDVInvokedUrlCommand*)command {
+ [self shareInternal:command
+ withOptions:@{
+ kShareOptionMessage: [command.arguments objectAtIndex:0],
+ kShareOptionSubject: [command.arguments objectAtIndex:1],
+ kShareOptionFiles: [command.arguments objectAtIndex:2],
+ kShareOptionUrl: [command.arguments objectAtIndex:3]
+ }
+ isBooleanResponse:YES
+];
+}
+
+- (void)shareWithOptions:(CDVInvokedUrlCommand*)command {
+ NSDictionary* options = [command.arguments objectAtIndex:0];
+ [self shareInternal:command
+ withOptions:options
+ isBooleanResponse:NO
+ ];
+}
+
+- (void)shareInternal:(CDVInvokedUrlCommand*)command withOptions:(NSDictionary*)options isBooleanResponse:(BOOL)boolResponse {
[self.commandDelegate runInBackground:^{ //avoid main thread block especially if sharing big files from url
if (!NSClassFromString(@"UIActivityViewController")) {
CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"not available"];
@@ -59,10 +84,10 @@ - (void)share:(CDVInvokedUrlCommand*)command {
return;
}
- NSString *message = [command.arguments objectAtIndex:0];
- NSString *subject = [command.arguments objectAtIndex:1];
- NSArray *filenames = [command.arguments objectAtIndex:2];
- NSString *urlString = [command.arguments objectAtIndex:3];
+ NSString *message = options[kShareOptionMessage];
+ NSString *subject = options[kShareOptionSubject];
+ NSArray *filenames = options[kShareOptionFiles];
+ NSString *urlString = options[kShareOptionUrl];
NSMutableArray *activityItems = [[NSMutableArray alloc] init];
[activityItems addObject:message];
@@ -93,21 +118,26 @@ - (void)share:(CDVInvokedUrlCommand*)command {
}
if ([activityVC respondsToSelector:(@selector(setCompletionWithItemsHandler:))]) {
- [activityVC setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError) {
- [self cleanupStoredFiles];
- NSLog(@"SocialSharing app selected: %@", activityType);
- CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:completed];
- [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
- }];
- }else{
+ [activityVC setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError) {
+ [self cleanupStoredFiles];
+ if (boolResponse) {
+ [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:completed]
+ callbackId:command.callbackId];
+ } else {
+ NSDictionary * result = @{@"completed":@(completed), @"app":activityType == nil ? @"" : activityType};
+ [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result]
+ callbackId:command.callbackId];
+ }
+ }];
+ } else {
// let's suppress this warning otherwise folks will start opening issues while it's not relevant
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- [activityVC setCompletionHandler:^(NSString *activityType, BOOL completed) {
- [self cleanupStoredFiles];
- NSLog(@"SocialSharing app selected: %@", activityType);
- CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:completed];
- [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
- }];
+ [activityVC setCompletionHandler:^(NSString *activityType, BOOL completed) {
+ [self cleanupStoredFiles];
+ NSDictionary * result = @{@"completed":@(completed), @"app":activityType};
+ CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result];
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+ }];
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
}
diff --git a/www/SocialSharing.js b/www/SocialSharing.js
index f056c9fd..823bca78 100644
--- a/www/SocialSharing.js
+++ b/www/SocialSharing.js
@@ -25,6 +25,11 @@ SocialSharing.prototype.available = function (callback) {
}, null, "SocialSharing", "available", []);
};
+// this is the recommended way to share as it is the most feature-rich with respect to what you pass in and get back
+SocialSharing.prototype.shareWithOptions = function (options, successCallback, errorCallback) {
+ cordova.exec(successCallback, this._getErrorCallback(errorCallback, "shareWithOptions"), "SocialSharing", "shareWithOptions", [options]);
+};
+
SocialSharing.prototype.share = function (message, subject, fileOrFileArray, url, successCallback, errorCallback) {
cordova.exec(successCallback, this._getErrorCallback(errorCallback, "share"), "SocialSharing", "share", [message, subject, this._asArray(fileOrFileArray), url]);
};