├── .DS_Store ├── README.md ├── package.json ├── plugin.xml ├── src ├── android │ └── Sms.java ├── ios │ ├── Sms.h │ └── Sms.m └── wp8 │ └── Sms.cs └── www └── sms.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazems/cordova-sms-plugin/2041f0a0f26e92b1e807d52f2dc2c905536c542f/.DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Notice: 2 | ==================== 3 | This plugin is one of the examples of the ["JavaScript Mobile Application Development"](https://www.packtpub.com/web-development/javascript-native-mobile-apps-development) book which can be reached at:
4 | [http://www.amazon.com/JavaScript-Native-Mobile-Apps-Development/dp/1783554177/](http://www.amazon.com/JavaScript-Native-Mobile-Apps-Development/dp/1783554177/)
5 | [https://www.packtpub.com/web-development/javascript-native-mobile-apps-development](http://www.amazon.com/JavaScript-Native-Mobile-Apps-Development/dp/1783554177/) 6 | 7 | Sms Custom Cordova Plugin: 8 | ==================== 9 | This plugin allows you to send SMS message to a specific phone number for Android, iOS and Windows Platform 8. Here is an example below: 10 | 11 | 12 | var messageInfo = { 13 | phoneNumber: "xxxxxxxxxx", 14 | textMessage: "This is a test message" 15 | }; 16 | 17 | sms.sendMessage(messageInfo, function(message) { 18 | console.log("success: " + message); 19 | }, function(error) { 20 | console.log("code: " + error.code + ", message: " + error.message); 21 | }); 22 | 23 | As you notice you just need to call *sms.sendMessage(messageInfo, successCallback, failureCallback)*: 24 | 25 | * *messageInfo* is a JSON object which contains phoneNumber and textMessage attributes. 26 | * *sucessCallback* is a callback function which will be called if the send SMS operation succeeds. 27 | * *errorCallback* is a callback function which will be called if the send SMS operation fails. 28 | 29 | Installing the plugin 30 | --- 31 | In order to install the plugin you can: 32 | 33 | Install it from NPM registry as follows: 34 | 35 | npm i hazems-cordova-plugin-sms 36 | 37 | 38 | or simply use the following Cordova CLI command: 39 | 40 | cordova plugin add https://github.com/hazems/cordova-sms-plugin.git 41 | 42 | or 43 | 44 | cordova plugin add com.jsmobile.plugins.sms 45 | 46 | 47 | 48 | Important Note 49 | --- 50 | For iOS and Windows Phone platforms, it is not possible to send SMS directly without opening the default device SMS application. This means that the API will only open and track the SMS application events (cancel, successful sending, un-successful sending, ...etc) in iOS platform. For Windows Phone 8, the plugin will only open the SMS application without tracking its events because tracking SMS application events is not currently applicable in Windows 8 platform. 51 | 52 | Test Client 53 | --- 54 | You can reach the test client of this plugin here: 55 | [https://github.com/hazems/cordova-sms-plugin-test/ ](https://github.com/hazems/cordova-sms-plugin-test/) 56 | 57 | Used Resources 58 | --- 59 | Special Thanks to [appcoda.com]() for helping me in implementing the iOS part of this plugin: 60 | 61 | [http://www.appcoda.com/ios-programming-send-sms-text-message/ ](http://www.appcoda.com/ios-programming-send-sms-text-message/) 62 | 63 | Licence 64 | --- 65 | It is Apache License, Version 2.0. Feel free to fork the project and send pull requests if you have any. 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hazems-cordova-plugin-sms", 3 | "version": "0.0.2", 4 | "description": "A plugin for sending sms messages", 5 | "cordova": { 6 | "id": "com.jsmobile.plugins.sms", 7 | "platforms": [ 8 | "android", 9 | "ios", 10 | "wp8" 11 | ] 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/hazems/cordova-sms-plugin.git" 16 | }, 17 | "keywords": [ 18 | "cordova", 19 | "plugins", 20 | "sms", 21 | "ecosystem:cordova", 22 | "cordova-android", 23 | "cordova-ios", 24 | "cordova-wp8" 25 | ], 26 | "author": "Hazem Saleh", 27 | "license": "Apache 2.0", 28 | "bugs": { 29 | "url": "https://github.com/hazems/cordova-sms-plugin/issues" 30 | }, 31 | "homepage": "https://github.com/hazems/cordova-sms-plugin#readme" 32 | } 33 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | sms 4 | A plugin for sending sms messages 5 | Apache 2.0 6 | cordova,plugins,sms 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/android/Sms.java: -------------------------------------------------------------------------------- 1 | package com.jsmobile.plugins.sms; 2 | 3 | import org.apache.cordova.CordovaPlugin; 4 | import org.apache.cordova.CallbackContext; 5 | import org.apache.cordova.PluginResult; 6 | import org.apache.cordova.PluginResult.Status; 7 | import org.json.JSONArray; 8 | import org.json.JSONException; 9 | import org.json.JSONObject; 10 | 11 | import android.app.Activity; 12 | import android.app.PendingIntent; 13 | import android.content.BroadcastReceiver; 14 | import android.content.Context; 15 | import android.content.Intent; 16 | import android.content.IntentFilter; 17 | import android.content.pm.PackageManager; 18 | import android.telephony.SmsManager; 19 | 20 | /** 21 | * This class echoes a string called from JavaScript. 22 | */ 23 | //Changed from CDNsms to sms 24 | public class Sms extends CordovaPlugin { 25 | private static final String SMS_GENERAL_ERROR = "SMS_GENERAL_ERROR"; 26 | private static final String NO_SMS_SERVICE_AVAILABLE = "NO_SMS_SERVICE_AVAILABLE"; 27 | private static final String SMS_FEATURE_NOT_SUPPORTED = "SMS_FEATURE_NOT_SUPPORTED"; 28 | private static final String SENDING_SMS_ID = "SENDING_SMS"; 29 | 30 | @Override 31 | public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { 32 | if (action.equals("sendMessage")) { 33 | String phoneNumber = args.getString(0); 34 | String message = args.getString(1); 35 | 36 | boolean isSupported = getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY); 37 | 38 | if (! isSupported) { 39 | JSONObject errorObject = new JSONObject(); 40 | 41 | errorObject.put("code", SMS_FEATURE_NOT_SUPPORTED); 42 | errorObject.put("message", "SMS feature is not supported on this device"); 43 | 44 | callbackContext.sendPluginResult(new PluginResult(Status.ERROR, errorObject)); 45 | return false; 46 | } 47 | 48 | this.sendSMS(phoneNumber, message, callbackContext); 49 | 50 | return true; 51 | } 52 | 53 | return false; 54 | } 55 | 56 | private void sendSMS(String phoneNumber, String message, final CallbackContext callbackContext) throws JSONException { 57 | PendingIntent sentPI = PendingIntent.getBroadcast(getActivity(), 0, new Intent(SENDING_SMS_ID), 0); 58 | 59 | getActivity().registerReceiver(new BroadcastReceiver() { 60 | @Override 61 | public void onReceive(Context context, Intent intent) { 62 | switch (getResultCode()) { 63 | case Activity.RESULT_OK: 64 | callbackContext.sendPluginResult(new PluginResult(Status.OK, "SMS message is sent successfully")); 65 | break; 66 | case SmsManager.RESULT_ERROR_NO_SERVICE: 67 | try { 68 | JSONObject errorObject = new JSONObject(); 69 | 70 | errorObject.put("code", NO_SMS_SERVICE_AVAILABLE); 71 | errorObject.put("message", "SMS is not sent because no service is available"); 72 | 73 | callbackContext.sendPluginResult(new PluginResult(Status.ERROR, errorObject)); 74 | } catch (JSONException exception) { 75 | exception.printStackTrace(); 76 | } 77 | break; 78 | default: 79 | try { 80 | JSONObject errorObject = new JSONObject(); 81 | 82 | errorObject.put("code", SMS_GENERAL_ERROR); 83 | errorObject.put("message", "SMS general error"); 84 | 85 | callbackContext.sendPluginResult(new PluginResult(Status.ERROR, errorObject)); 86 | } catch (JSONException exception) { 87 | exception.printStackTrace(); 88 | } 89 | 90 | break; 91 | } 92 | } 93 | }, new IntentFilter(SENDING_SMS_ID)); 94 | 95 | SmsManager sms = SmsManager.getDefault(); 96 | 97 | sms.sendTextMessage(phoneNumber, null, message, sentPI, null); 98 | } 99 | 100 | private Activity getActivity() { 101 | return this.cordova.getActivity(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/ios/Sms.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface Sms : CDVPlugin { 5 | // Member variables go here. 6 | 7 | } 8 | 9 | @property(strong) NSString* callbackID; 10 | - (void)sendMessage:(CDVInvokedUrlCommand*)command; 11 | @end -------------------------------------------------------------------------------- /src/ios/Sms.m: -------------------------------------------------------------------------------- 1 | /********* Sms.m Cordova Plugin Implementation *******/ 2 | 3 | #import "Sms.h" 4 | 5 | @implementation Sms 6 | 7 | - (void)sendMessage:(CDVInvokedUrlCommand*)command 8 | { 9 | CDVPluginResult* pluginResult = nil; 10 | NSString* phoneNumber = [command.arguments objectAtIndex:0]; 11 | NSString* textMessage = [command.arguments objectAtIndex:1]; 12 | 13 | self.callbackID = command.callbackId; 14 | 15 | if (![MFMessageComposeViewController canSendText]) { 16 | NSMutableDictionary* returnInfo = [NSMutableDictionary dictionaryWithCapacity:2]; 17 | 18 | [returnInfo setObject:@"SMS_FEATURE_NOT_SUPPORTED" forKey:@"code"]; 19 | [returnInfo setObject:@"SMS feature is not supported on this device" forKey:@"message"]; 20 | 21 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:returnInfo]; 22 | 23 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 24 | 25 | return; 26 | } 27 | 28 | MFMessageComposeViewController *composeViewController = [[MFMessageComposeViewController alloc] init]; 29 | composeViewController.messageComposeDelegate = self; 30 | 31 | NSMutableArray *recipients = [[NSMutableArray alloc] init]; 32 | 33 | [recipients addObject:phoneNumber]; 34 | 35 | [composeViewController setBody:textMessage]; 36 | [composeViewController setRecipients:recipients]; 37 | 38 | [self.viewController presentViewController:composeViewController animated:YES completion:nil]; 39 | } 40 | 41 | // Handle the different situations of MFMessageComposeViewControllerDelegate 42 | - (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result { 43 | BOOL succeeded = NO; 44 | NSString* errorCode = @""; 45 | NSString* message = @""; 46 | 47 | switch(result) { 48 | case MessageComposeResultSent: 49 | succeeded = YES; 50 | message = @"Message sent"; 51 | break; 52 | case MessageComposeResultCancelled: 53 | message = @"Message cancelled"; 54 | errorCode = @"SMS_MESSAGE_CANCELLED"; 55 | break; 56 | case MessageComposeResultFailed: 57 | message = @"Message Compose Result failed"; 58 | errorCode = @"SMS_MESSAGE_COMPOSE_FAILED"; 59 | break; 60 | default: 61 | message = @"Sms General error"; 62 | errorCode = @"SMS_GENERAL_ERROR"; 63 | break; 64 | } 65 | 66 | [self.viewController dismissViewControllerAnimated:YES completion:nil]; 67 | 68 | if (succeeded == YES) { 69 | [super writeJavascript:[[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message] 70 | toSuccessCallbackString:self.callbackID]]; 71 | } else { 72 | NSMutableDictionary* returnInfo = [NSMutableDictionary dictionaryWithCapacity:2]; 73 | 74 | [returnInfo setObject:errorCode forKey:@"code"]; 75 | [returnInfo setObject:message forKey:@"message"]; 76 | 77 | [super writeJavascript:[[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:returnInfo] 78 | toErrorCallbackString:self.callbackID]]; 79 | } 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /src/wp8/Sms.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Phone.Tasks; 3 | using WPCordovaClassLib.Cordova; 4 | using WPCordovaClassLib.Cordova.Commands; 5 | using WPCordovaClassLib.Cordova.JSON; 6 | 7 | namespace WPCordovaClassLib.Cordova.Commands 8 | { 9 | public class Sms : BaseCommand 10 | { 11 | 12 | public void sendMessage(string options) 13 | { 14 | string[] optValues = JsonHelper.Deserialize(options); 15 | String number = optValues[0]; 16 | String message = optValues[1]; 17 | 18 | SmsComposeTask sms = new SmsComposeTask(); 19 | 20 | sms.To = number; 21 | sms.Body = message; 22 | 23 | sms.Show(); 24 | 25 | //Since there is no way to track SMS application events in WP8, always send Ok status. 26 | DispatchCommandResult(new PluginResult(PluginResult.Status.OK, "Success")); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /www/sms.js: -------------------------------------------------------------------------------- 1 | var smsExport = {}; 2 | 3 | smsExport.sendMessage = function(messageInfo, successCallback, errorCallback) { 4 | if (messageInfo == null || typeof messageInfo !== 'object') { 5 | 6 | if (errorCallback) { 7 | errorCallback({ 8 | code: "INVALID_INPUT", 9 | message: "Invalid Input" 10 | }); 11 | } 12 | 13 | return; 14 | } 15 | 16 | var phoneNumber = messageInfo.phoneNumber; 17 | var textMessage = messageInfo.textMessage || ""; 18 | 19 | if (! phoneNumber) { 20 | console.log("Missing Phone Number"); 21 | 22 | if (errorCallback) { 23 | errorCallback({ 24 | code: "MISSING_PHONE_NUMBER", 25 | message: "Missing Phone number" 26 | }); 27 | } 28 | 29 | return; 30 | } 31 | 32 | cordova.exec(successCallback, errorCallback, "Sms", "sendMessage", [phoneNumber, textMessage]); 33 | }; 34 | 35 | module.exports = smsExport; 36 | --------------------------------------------------------------------------------