diff --git a/plugin.xml b/plugin.xml
index eb282b4..ab777fd 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -23,12 +23,27 @@
+
+
+
+
+
+
+
diff --git a/src/android/Sms.java b/src/android/Sms.java
index 5244a07..c37eecb 100644
--- a/src/android/Sms.java
+++ b/src/android/Sms.java
@@ -12,13 +12,26 @@
import android.os.Build;
import android.provider.Telephony;
import android.telephony.SmsManager;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import android.util.Base64;
import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
+import org.json.JSONObject;
import org.json.JSONException;
+import androidx.core.content.FileProvider;
+
public class Sms extends CordovaPlugin {
public final String ACTION_SEND_SMS = "send";
@@ -103,6 +116,11 @@ public void run() {
String message = args.getString(1);
String method = args.getString(2);
boolean replaceLineBreaks = Boolean.parseBoolean(args.getString(3));
+ JSONObject attachments = null;
+
+ if (!args.isNull(4)) {
+ attachments = args.getJSONObject(4);
+ }
// replacing \n by new line if the parameter replaceLineBreaks is set to true
if (replaceLineBreaks) {
@@ -113,9 +131,7 @@ public void run() {
return;
}
if (method.equalsIgnoreCase("INTENT")) {
- invokeSMSIntent(phoneNumber, message);
- // always passes success back to the app
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
+ invokeSMSIntent(phoneNumber, message, attachments);
} else {
send(callbackContext, phoneNumber, message);
}
@@ -134,18 +150,66 @@ private boolean checkSupport() {
}
@SuppressLint("NewApi")
- private void invokeSMSIntent(String phoneNumber, String message) {
+ private void invokeSMSIntent(String phoneNumber, String message, JSONObject attachments) {
Intent sendIntent;
- if ("".equals(phoneNumber) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ List images = null;
+
+ if (attachments != null) {
+ Iterator keys = attachments.keys();
+ while(keys.hasNext()) {
+ String fileName = keys.next();
+ String base64String;
+ try {
+ base64String = attachments.getString(fileName);
+ } catch (JSONException e) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+ return;
+ }
+ byte[] imgBytes = Base64.decode(base64String, Base64.DEFAULT);
+
+ File tmpDir = cordova.getContext().getCacheDir();
+ File imgFile = new File(tmpDir, fileName);
+
+ try {
+ imgFile.createNewFile();
+ } catch (IOException e) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION));
+ }
+
+ try (OutputStream stream = new FileOutputStream(imgFile)) {
+ stream.write(imgBytes);
+ } catch (NullPointerException e) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR));
+ } catch (IOException e) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION));
+ }
+ if (images == null) {
+ images = new ArrayList<>();
+ }
+ images.add(imgFile);
+ }
+ }
+
+ final boolean hasImage = images != null;
+ final boolean hasMultipleImages = hasImage && images.size() > 1;
+ final boolean emptyPhoneNumber = "".equals(phoneNumber);
+
+ if ((emptyPhoneNumber || hasImage) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
String defaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(this.cordova.getActivity());
- sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.setType("text/plain");
+ sendIntent = new Intent(hasMultipleImages ? Intent.ACTION_SEND_MULTIPLE : Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, message);
+ if (!emptyPhoneNumber) {
+ // See http://stackoverflow.com/questions/7242190/sending-sms-using-intent-does-not-add-recipients-on-some-devices
+ sendIntent.putExtra("address", phoneNumber);
+ sendIntent.setData(Uri.parse("smsto:" + Uri.encode(phoneNumber)));
+ }
+
if (defaultSmsPackageName != null) {
sendIntent.setPackage(defaultSmsPackageName);
}
+ sendIntent.setType( hasImage ? "image/*" : "text/plain");
} else {
sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.putExtra("sms_body", message);
@@ -153,6 +217,22 @@ private void invokeSMSIntent(String phoneNumber, String message) {
sendIntent.putExtra("address", phoneNumber);
sendIntent.setData(Uri.parse("smsto:" + Uri.encode(phoneNumber)));
}
+
+ if (hasImage) {
+ String FILE_AUTHORITY = cordova.getContext().getPackageName() + ".cordova.plugins.sms.fileprovider";
+
+ ArrayList imageUris = images.stream()
+ .map(file -> FileProvider.getUriForFile(cordova.getContext(), FILE_AUTHORITY, file))
+ .collect(Collectors.toCollection(ArrayList::new));
+ if (hasMultipleImages) {
+ sendIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
+ } else {
+ sendIntent.putExtra(Intent.EXTRA_STREAM, imageUris.get(0));
+ }
+ sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ }
+
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
this.cordova.getActivity().startActivity(sendIntent);
}
diff --git a/src/android/xml/cordova_sms_filepaths.xml b/src/android/xml/cordova_sms_filepaths.xml
new file mode 100644
index 0000000..e7d109d
--- /dev/null
+++ b/src/android/xml/cordova_sms_filepaths.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/ios/Sms.m b/src/ios/Sms.m
index 202cb8a..b39947e 100644
--- a/src/ios/Sms.m
+++ b/src/ios/Sms.m
@@ -47,6 +47,21 @@ - (void)send:(CDVInvokedUrlCommand*)command {
[composeViewController setRecipients:recipients];
}
+
+ NSMutableDictionary* attachments = [command.arguments objectAtIndex:4];
+ if (attachments != nil && ![attachments isEqual:[NSNull null]]) {
+ for (NSString* filename in attachments) {
+ NSString* imgStr = [attachments objectForKey:filename];
+ NSData *data = [[NSData alloc] initWithBase64EncodedString:imgStr options:0];
+ UIImage *image = [UIImage imageWithData:data];
+ if (image != nil) {
+ NSData* attachment = UIImageJPEGRepresentation(image, 1.0);
+ [composeViewController
+ addAttachmentData:attachment
+ typeIdentifier:@"public.jpeg" filename:filename];
+ }
+ }
+ }
[self.viewController presentViewController:composeViewController animated:YES completion:nil];
});
}];
diff --git a/www/sms.js b/www/sms.js
index 1d68baf..eb94bd5 100644
--- a/www/sms.js
+++ b/www/sms.js
@@ -22,6 +22,7 @@ sms.send = function(phone, message, options, success, failure) {
// parsing options
var replaceLineBreaks = false;
var androidIntent = '';
+ var attachments = null;
if (typeof options === 'string') { // ensuring backward compatibility
window.console.warn('[DEPRECATED] Passing a string as a third argument is deprecated. Please refer to the documentation to pass the right parameter: https://github.com/cordova-sms/cordova-sms-plugin.');
androidIntent = options;
@@ -31,6 +32,9 @@ sms.send = function(phone, message, options, success, failure) {
if (options.android && typeof options.android === 'object') {
androidIntent = options.android.intent;
}
+ if (options.attachments) {
+ attachments = options.attachments;
+ }
}
// fire
@@ -38,7 +42,7 @@ sms.send = function(phone, message, options, success, failure) {
success,
failure,
'Sms',
- 'send', [phone, message, androidIntent, replaceLineBreaks]
+ 'send', [phone, message, androidIntent, replaceLineBreaks, attachments]
);
};