From 8053175c53db45c660515b57c3b7c6c3dbb8c999 Mon Sep 17 00:00:00 2001 From: Lyle Pratt Date: Fri, 19 Jul 2013 12:49:52 -0500 Subject: [PATCH 1/7] Updated plugin for use with Cordova 2.9. Added two functions to manage displaying a UILocalNotification to the user in the event of an incoming call while the app is in a backgrounded state. --- README.md | 12 +++++++++++ iOS/TCPlugin.h | 3 +++ iOS/TCPlugin.m | 57 ++++++++++++++++++++++++++++++++++++++++++++++++- iOS/tcPlugin.js | 31 ++++++++++++++++++++------- 4 files changed, 94 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9698e3f..6177284 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,18 @@ This is a Phonegap plugin that exposes the same JS API as Twilio Client for web +## Additional iOS Features + +In addition to the standard features of the Twilio Client JS Library, you can also use the included showNotification and cancelNotification functions to display an iOS UILocalNotifcation to the user when during an incoming call while the app is running in the background: + +```javascript +Twilio.Connection.showNotification("Notification Text", "notification_sound.wav"); +``` + +```javascript +Twilio.Connection.cancelNotification(); +``` + ## Limitations This is plugin is a first cut and should be considered alpha. Please use it and break it :) Report any issues using the Github issue tracker. diff --git a/iOS/TCPlugin.h b/iOS/TCPlugin.h index 4ac8be6..a5232f7 100644 --- a/iOS/TCPlugin.h +++ b/iOS/TCPlugin.h @@ -33,7 +33,10 @@ -(void)disconnectAll:(NSArray *)arguments withDict:(NSMutableDictionary *)options; -(void)acceptConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)options; -(void)disconnectConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)options; +-(void)rejectConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)options; -(void)muteConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)options; -(void)sendDigits:(NSMutableArray *)arguments withDict:(NSMutableDictionary *)options; +-(void)showNotification:(CDVInvokedUrlCommand*)command; +-(void)cancelNotification:(CDVInvokedUrlCommand*)command; @end \ No newline at end of file diff --git a/iOS/TCPlugin.m b/iOS/TCPlugin.m index 0360734..b2b4f2d 100644 --- a/iOS/TCPlugin.m +++ b/iOS/TCPlugin.m @@ -1,6 +1,6 @@ // // TCPlugin.h -// Twilio Client plugin for PhoneGap +// Twilio Client plugin for PhoneGap / Cordova // // Copyright 2012 Stevie Graham. // @@ -16,6 +16,7 @@ @interface TCPlugin() { @property(nonatomic, strong) TCDevice *device; @property(nonatomic, strong) NSString *callback; @property(atomic, strong) TCConnection *connection; +@property(atomic, strong) UILocalNotification *ringNotification; -(void)javascriptCallback:(NSString *)event; -(void)javascriptCallback:(NSString *)event withArguments:(NSDictionary *)arguments; @@ -28,6 +29,7 @@ @implementation TCPlugin @synthesize device = _device; @synthesize callback = _callback; @synthesize connection = _connection; +@synthesize ringNotification = _ringNotification; # pragma mark device delegate method @@ -36,6 +38,7 @@ -(void)device:(TCDevice *)device didStopListeningForIncomingConnections:(NSError } -(void)device:(TCDevice *)device didReceiveIncomingConnection:(TCConnection *)connection { + self.connection = connection; [self javascriptCallback:@"onincoming"]; } @@ -128,6 +131,10 @@ -(void)disconnectConnection:(NSArray *)arguments withDict:(NSMutableDictionary * [self.connection disconnect]; } +-(void)rejectConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)options { + [self.connection reject]; +} + -(void)muteConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)options { if(self.connection.isMuted) { self.connection.muted = NO; @@ -166,6 +173,54 @@ -(void)connectionStatus:(NSMutableArray *)arguments withDict:(NSMutableDictionar [self performSelectorOnMainThread:@selector(writeJavascript:) withObject:[result toSuccessCallbackString:[arguments pop]] waitUntilDone:NO]; } + +-(void)showNotification:(CDVInvokedUrlCommand*)command { + @try { + [[UIApplication sharedApplication] cancelAllLocalNotifications]; + } + @catch(NSException *exception) { + NSLog(@"Couldn't Cancel Notification"); + } + + NSString *alertBody = [command.arguments objectAtIndex:0]; + + NSString *ringSound = @"incoming.wav"; + + @try { + ringSound = [command.arguments objectAtIndex:1]; + NSString* fileName = [[ringSound lastPathComponent] stringByDeletingPathExtension]; + NSString* extension = [ringSound pathExtension]; + NSBundle *myBundle = [NSBundle mainBundle]; + NSString *pathToFile = [myBundle pathForResource:fileName ofType:extension]; + if (pathToFile == nil) { + NSLog(@"Couldn't find notification sound."); + ringSound = @"incoming.wav"; + } + else { + + } + } + @catch (NSException *exception) { + NSLog(@"Couldn't find notification sound."); + ringSound = @"incoming.wav"; + } + + _ringNotification = [[UILocalNotification alloc] init]; + _ringNotification.alertBody = alertBody; + _ringNotification.alertAction = @"Answer"; + _ringNotification.soundName = ringSound; + _ringNotification.fireDate = [NSDate date]; + //_ringNotification.repeatInterval = nil; + //_ringNotification.userInfo = [NSDictionary dictionaryWithObjectsAndKeys: 0, @"notificationId", 0, @"callbackId", nil]; + //[[UIApplication sharedApplication] presentLocalNotificationNow:_ringNotification]; + [[UIApplication sharedApplication] scheduleLocalNotification:_ringNotification]; + +} + +-(void)cancelNotification:(CDVInvokedUrlCommand*)command { + [[UIApplication sharedApplication] cancelLocalNotification:_ringNotification]; +} + # pragma mark private methods -(void)javascriptCallback:(NSString *)event withArguments:(NSDictionary *)arguments { diff --git a/iOS/tcPlugin.js b/iOS/tcPlugin.js index d5be4b7..b285dc3 100644 --- a/iOS/tcPlugin.js +++ b/iOS/tcPlugin.js @@ -36,7 +36,7 @@ } TwilioPlugin.Device.prototype.disconnectAll = function() { - Cordova.exec('TCPlugin.disconnectAll'); + Cordova.exec(null, null, "TCPlugin", "disconnectAll", []); } TwilioPlugin.Device.prototype.disconnect = function(fn) { @@ -68,33 +68,47 @@ } TwilioPlugin.Device.prototype.status = function() { - var status = Cordova.exec("TCPlugin.deviceStatus"); + Cordova.exec(null, null, "TCPlugin", "deviceStatus", []); } // Noops until I figure out why the hell using sounds in Phonegap gives EXC_BAD_ACCESS + TwilioPlugin.Device.prototype.sounds = { incoming: function(boolean) {}, outgoing: function(boolean) {}, disconnect: function(boolean) {} } + TwilioPlugin.Connection.prototype.accept = function(argument) { if (typeof(argument) == 'function') { delegate['onaccept'] = argument; } else { - Cordova.exec("TCPlugin.acceptConnection"); + Cordova.exec(null, null, "TCPlugin", "acceptConnection", [argument]); } } + TwilioPlugin.Connection.prototype.showNotification = function(alertBody, ringSound) { + var args = [alertBody, ringSound]; + if(ringSound === "undefined") { + args = [alertBody]; + } + Cordova.exec(null, null, "TCPlugin", "showNotification", args); + } + + TwilioPlugin.Connection.prototype.cancelNotification = function() { + Cordova.exec(null, null, "TCPlugin", "cancelNotification", []); + } + TwilioPlugin.Connection.prototype.reject = function() { - Cordova.exec("TCPlugin.rejectConnection"); + Cordova.exec(null, null, "TCPlugin", "rejectConnection", []); } TwilioPlugin.Connection.prototype.disconnect = function(fn) { if (typeof(argument) == 'function') { delegate['onconnectiondisconnect'] = argument; } else { - Cordova.exec("TCPlugin.disconnectConnection"); + Cordova.exec(null, null, "TCPlugin", "disconnectConnection", []); } } @@ -103,15 +117,16 @@ } TwilioPlugin.Connection.prototype.mute = function() { - Cordova.exec("TCPlugin.muteConnection"); + Cordova.exec(null, null, "TCPlugin", "muteConnection", []); } TwilioPlugin.Connection.prototype.unmute = function() { - Cordova.exec("TCPlugin.muteConnection"); + Cordova.exec(null, null, "TCPlugin", "muteConnection", []); } TwilioPlugin.Connection.prototype.sendDigits = function(string) { - Cordova.exec("TCPlugin.sendDigits", string); + //Cordova.exec("TCPlugin.sendDigits", string); + Cordova.exec(null, null, "TCPlugin", "sendDigits", [string]); } TwilioPlugin.Connection.prototype.status = function(fn) { From d982e16b118cd1f00ef4917f65f1abb8f9007c53 Mon Sep 17 00:00:00 2001 From: Lyle Pratt Date: Sun, 21 Jul 2013 16:42:14 -0500 Subject: [PATCH 2/7] Added helper method to turn speaker phone on or off. Fixed bug with sendDigits. --- iOS/TCPlugin.h | 3 ++- iOS/TCPlugin.m | 30 +++++++++++++++++++++++++----- iOS/tcPlugin.js | 11 ++++++++--- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/iOS/TCPlugin.h b/iOS/TCPlugin.h index a5232f7..265a7b7 100644 --- a/iOS/TCPlugin.h +++ b/iOS/TCPlugin.h @@ -35,8 +35,9 @@ -(void)disconnectConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)options; -(void)rejectConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)options; -(void)muteConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)options; --(void)sendDigits:(NSMutableArray *)arguments withDict:(NSMutableDictionary *)options; +-(void)sendDigits:(CDVInvokedUrlCommand*)command; -(void)showNotification:(CDVInvokedUrlCommand*)command; -(void)cancelNotification:(CDVInvokedUrlCommand*)command; +-(void)setSpeaker:(CDVInvokedUrlCommand*)command; @end \ No newline at end of file diff --git a/iOS/TCPlugin.m b/iOS/TCPlugin.m index b2b4f2d..6261e1b 100644 --- a/iOS/TCPlugin.m +++ b/iOS/TCPlugin.m @@ -82,9 +82,9 @@ -(void)deviceSetup:(NSMutableArray *)arguments withDict:(NSMutableDictionary*)op self.device = [[TCDevice alloc] initWithCapabilityToken:[arguments pop] delegate:self]; // Disable sounds. was getting EXC_BAD_ACCESS - self.device.incomingSoundEnabled = NO; - self.device.outgoingSoundEnabled = NO; - self.device.disconnectSoundEnabled = NO; + //self.device.incomingSoundEnabled = NO; + //self.device.outgoingSoundEnabled = NO; + //self.device.disconnectSoundEnabled = NO; [self javascriptCallback:@"onready"]; } @@ -143,8 +143,8 @@ -(void)muteConnection:(NSArray *)arguments withDict:(NSMutableDictionary *)optio } } --(void)sendDigits:(NSMutableArray *)arguments withDict:(NSMutableDictionary *)options { - [self.connection sendDigits:[arguments pop]]; +-(void)sendDigits:(CDVInvokedUrlCommand*)command { + [self.connection sendDigits:[command.arguments objectAtIndex:0]]; } -(void)connectionStatus:(NSMutableArray *)arguments withDict:(NSMutableDictionary *)options { @@ -221,6 +221,26 @@ -(void)cancelNotification:(CDVInvokedUrlCommand*)command { [[UIApplication sharedApplication] cancelLocalNotification:_ringNotification]; } +-(void)setSpeaker:(CDVInvokedUrlCommand*)command { + NSString *mode = [command.arguments objectAtIndex:0]; + if([mode isEqual: @"on"]) { + UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; + AudioSessionSetProperty ( + kAudioSessionProperty_OverrideAudioRoute, + sizeof (audioRouteOverride), + &audioRouteOverride + ); + } + else { + UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None; + AudioSessionSetProperty ( + kAudioSessionProperty_OverrideAudioRoute, + sizeof (audioRouteOverride), + &audioRouteOverride + ); + } +} + # pragma mark private methods -(void)javascriptCallback:(NSString *)event withArguments:(NSDictionary *)arguments { diff --git a/iOS/tcPlugin.js b/iOS/tcPlugin.js index b285dc3..3ca5fce 100644 --- a/iOS/tcPlugin.js +++ b/iOS/tcPlugin.js @@ -74,9 +74,9 @@ // Noops until I figure out why the hell using sounds in Phonegap gives EXC_BAD_ACCESS TwilioPlugin.Device.prototype.sounds = { - incoming: function(boolean) {}, - outgoing: function(boolean) {}, - disconnect: function(boolean) {} + //incoming: function(boolean) {}, + //outgoing: function(boolean) {}, + //disconnect: function(boolean) {} } @@ -100,6 +100,11 @@ Cordova.exec(null, null, "TCPlugin", "cancelNotification", []); } + TwilioPlugin.Connection.prototype.setSpeaker = function(mode) { + // "on" or "off" + Cordova.exec(null, null, "TCPlugin", "setSpeaker", [mode]); + } + TwilioPlugin.Connection.prototype.reject = function() { Cordova.exec(null, null, "TCPlugin", "rejectConnection", []); } From 43377bb255136bbc80f62055564ed57c19b77c2b Mon Sep 17 00:00:00 2001 From: Lyle Pratt Date: Sun, 21 Jul 2013 16:44:59 -0500 Subject: [PATCH 3/7] Added documentation of new setSpeaker method. --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 6177284..4fcaef2 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ Twilio.Connection.showNotification("Notification Text", "notification_sound.wav" Twilio.Connection.cancelNotification(); ``` +You can also turn the device's speaker phone on or off during a call using the following method: + +```javascript +Twilio.Connection.setSpeaker("on"); +``` + ## Limitations This is plugin is a first cut and should be considered alpha. Please use it and break it :) Report any issues using the Github issue tracker. From 1e3cb7dada7ee0c72869ffe403328fd53973c248 Mon Sep 17 00:00:00 2001 From: Lyle Pratt Date: Sun, 21 Jul 2013 20:07:36 -0500 Subject: [PATCH 4/7] Removed commented code. Removed sound exists check. --- iOS/TCPlugin.m | 22 ++-------------------- iOS/tcPlugin.js | 2 +- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/iOS/TCPlugin.m b/iOS/TCPlugin.m index 6261e1b..ca804d4 100644 --- a/iOS/TCPlugin.m +++ b/iOS/TCPlugin.m @@ -185,24 +185,9 @@ -(void)showNotification:(CDVInvokedUrlCommand*)command { NSString *alertBody = [command.arguments objectAtIndex:0]; NSString *ringSound = @"incoming.wav"; - - @try { + NSLog([NSString stringWithFormat:@"%d", [command.arguments count]]); + if([command.arguments count] == 2) { ringSound = [command.arguments objectAtIndex:1]; - NSString* fileName = [[ringSound lastPathComponent] stringByDeletingPathExtension]; - NSString* extension = [ringSound pathExtension]; - NSBundle *myBundle = [NSBundle mainBundle]; - NSString *pathToFile = [myBundle pathForResource:fileName ofType:extension]; - if (pathToFile == nil) { - NSLog(@"Couldn't find notification sound."); - ringSound = @"incoming.wav"; - } - else { - - } - } - @catch (NSException *exception) { - NSLog(@"Couldn't find notification sound."); - ringSound = @"incoming.wav"; } _ringNotification = [[UILocalNotification alloc] init]; @@ -210,9 +195,6 @@ -(void)showNotification:(CDVInvokedUrlCommand*)command { _ringNotification.alertAction = @"Answer"; _ringNotification.soundName = ringSound; _ringNotification.fireDate = [NSDate date]; - //_ringNotification.repeatInterval = nil; - //_ringNotification.userInfo = [NSDictionary dictionaryWithObjectsAndKeys: 0, @"notificationId", 0, @"callbackId", nil]; - //[[UIApplication sharedApplication] presentLocalNotificationNow:_ringNotification]; [[UIApplication sharedApplication] scheduleLocalNotification:_ringNotification]; } diff --git a/iOS/tcPlugin.js b/iOS/tcPlugin.js index 3ca5fce..641a600 100644 --- a/iOS/tcPlugin.js +++ b/iOS/tcPlugin.js @@ -90,7 +90,7 @@ TwilioPlugin.Connection.prototype.showNotification = function(alertBody, ringSound) { var args = [alertBody, ringSound]; - if(ringSound === "undefined") { + if(ringSound == undefined) { args = [alertBody]; } Cordova.exec(null, null, "TCPlugin", "showNotification", args); From 08f2c500cb3bcdf10f141545a48297ec8324299e Mon Sep 17 00:00:00 2001 From: Lyle Pratt Date: Sun, 21 Jul 2013 20:15:31 -0500 Subject: [PATCH 5/7] Removed unneeded comment. --- iOS/TCPlugin.m | 1 - 1 file changed, 1 deletion(-) diff --git a/iOS/TCPlugin.m b/iOS/TCPlugin.m index ca804d4..fd7f2be 100644 --- a/iOS/TCPlugin.m +++ b/iOS/TCPlugin.m @@ -185,7 +185,6 @@ -(void)showNotification:(CDVInvokedUrlCommand*)command { NSString *alertBody = [command.arguments objectAtIndex:0]; NSString *ringSound = @"incoming.wav"; - NSLog([NSString stringWithFormat:@"%d", [command.arguments count]]); if([command.arguments count] == 2) { ringSound = [command.arguments objectAtIndex:1]; } From 2561ca36c5e8ac7659aefb0d0ef644046e01f686 Mon Sep 17 00:00:00 2001 From: Lyle Pratt Date: Fri, 2 Aug 2013 10:18:28 -0500 Subject: [PATCH 6/7] Altered how showNotification works in Android plugin. Added setSpeaker() method to Android plugin. Added reject() method to Android plugin. Misc bug fixes. --- .../IncomingConnectionActivity.java | 4 +- .../plugins/twilioclient/TCPlugin.java | 52 ++++++++++++++++++- .../phonegap/plugins/twilioclient/tcPlugin.js | 6 ++- iOS/tcPlugin.js | 9 ++-- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/Android/src/com/phonegap/plugins/twilioclient/IncomingConnectionActivity.java b/Android/src/com/phonegap/plugins/twilioclient/IncomingConnectionActivity.java index 83390b4..a6e140c 100644 --- a/Android/src/com/phonegap/plugins/twilioclient/IncomingConnectionActivity.java +++ b/Android/src/com/phonegap/plugins/twilioclient/IncomingConnectionActivity.java @@ -4,8 +4,8 @@ import android.content.Intent; import android.support.v4.content.LocalBroadcastManager; -import com.twilio.client.Connection; -import com.twilio.client.Device; +//import com.twilio.client.Connection; +//import com.twilio.client.Device; /** * diff --git a/Android/src/com/phonegap/plugins/twilioclient/TCPlugin.java b/Android/src/com/phonegap/plugins/twilioclient/TCPlugin.java index df1cf16..3d0f439 100644 --- a/Android/src/com/phonegap/plugins/twilioclient/TCPlugin.java +++ b/Android/src/com/phonegap/plugins/twilioclient/TCPlugin.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.media.AudioManager; import android.support.v4.app.NotificationCompat; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; @@ -70,7 +71,7 @@ public void onReceive(Context context, Intent intent) { if (mCurrentNotificationText != null) { - + /* PackageManager pm = context.getPackageManager(); Intent notificationIntent = pm.getLaunchIntentForPackage(context.getPackageName()); notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); @@ -88,6 +89,7 @@ public void onReceive(Context context, Intent intent) { (NotificationManager) TCPlugin.this.webView.getContext().getSystemService(Activity.NOTIFICATION_SERVICE); // Builds the notification and issues it. mNotifyMgr.notify(mCurrentNotificationId, mBuilder.build()); + */ } } catch (JSONException e) { @@ -153,6 +155,7 @@ public boolean execute(final String action, final JSONArray args, connectionStatus(callbackContext); return true; } else if ("rejectConnection".equals(action)) { + rejectConnection(args, callbackContext); return true; } else if ("showNotification".equals(action)) { showNotification(args,callbackContext); @@ -160,6 +163,9 @@ public boolean execute(final String action, final JSONArray args, } else if ("cancelNotification".equals(action)) { cancelNotification(args,callbackContext); return true; + } else if ("setSpeaker".equals(action)) { + setSpeaker(args,callbackContext); + return true; } return false; @@ -253,6 +259,11 @@ private void acceptConnection(JSONArray arguments, CallbackContext callbackConte callbackContext.success(); } + private void rejectConnection(JSONArray arguments, CallbackContext callbackContext) { + mConnection.reject(); + callbackContext.success(); + } + private void disconnectConnection(JSONArray arguments, CallbackContext callbackContext) { mConnection.disconnect(); callbackContext.success(); @@ -340,6 +351,23 @@ private void showNotification(JSONArray arguments, CallbackContext context) { (NotificationManager) TCPlugin.this.webView.getContext().getSystemService(Activity.NOTIFICATION_SERVICE); mNotifyMgr.cancelAll(); mCurrentNotificationText = arguments.optString(0); + + Context acontext = TCPlugin.this.webView.getContext(); + PackageManager pm = acontext.getPackageManager(); + Intent notificationIntent = pm.getLaunchIntentForPackage(acontext.getPackageName()); + notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + + PendingIntent pendingIntent = PendingIntent.getActivity(acontext, 0, notificationIntent, 0); + + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(acontext) + .setSmallIcon(R.drawable.btn_star_big_on) + .setContentTitle("Answer") + .setContentText(mCurrentNotificationText) + .setContentIntent(pendingIntent); + mNotifyMgr.notify(mCurrentNotificationId, mBuilder.build()); + + context.success(); } @@ -350,6 +378,28 @@ private void cancelNotification(JSONArray arguments, CallbackContext context) { context.success(); } + /** + * Changes sound from earpiece to speaker and back + * + * @param mode Speaker Mode + * */ + public void setSpeaker(JSONArray arguments, final CallbackContext callbackContext) { + Context context = cordova.getActivity().getApplicationContext(); + AudioManager m_amAudioManager; + m_amAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + String mode = arguments.optString(0); + if(mode.equals("on")) { + Log.d("TCPlugin", "SPEAKER"); + m_amAudioManager.setMode(AudioManager.MODE_NORMAL); + m_amAudioManager.setSpeakerphoneOn(true); + } + else { + Log.d("TCPlugin", "EARPIECE"); + m_amAudioManager.setMode(AudioManager.MODE_IN_CALL); + m_amAudioManager.setSpeakerphoneOn(false); + } + } + // DeviceListener methods @Override diff --git a/Android/src/com/phonegap/plugins/twilioclient/tcPlugin.js b/Android/src/com/phonegap/plugins/twilioclient/tcPlugin.js index d61d3e1..1175d36 100644 --- a/Android/src/com/phonegap/plugins/twilioclient/tcPlugin.js +++ b/Android/src/com/phonegap/plugins/twilioclient/tcPlugin.js @@ -72,7 +72,6 @@ var status = Cordova.exec(null,null,"TCPlugin","deviceStatus",[]); } - // Noops until I figure out why the hell using sounds in Phonegap gives EXC_BAD_ACCESS TwilioPlugin.Device.prototype.sounds = { incoming: function(boolean) {}, outgoing: function(boolean) {}, @@ -99,6 +98,11 @@ Cordova.exec(null, null, "TCPlugin", "cancelNotification", []); } + TwilioPlugin.Connection.prototype.setSpeaker = function(mode) { + // "on" or "off" + Cordova.exec(null, null, "TCPlugin", "setSpeaker", [mode]); + } + TwilioPlugin.Connection.prototype.reject = function() { Cordova.exec(null,null,"TCPlugin","rejectConnection",[]); } diff --git a/iOS/tcPlugin.js b/iOS/tcPlugin.js index 8028ffc..a1310b9 100644 --- a/iOS/tcPlugin.js +++ b/iOS/tcPlugin.js @@ -70,13 +70,11 @@ TwilioPlugin.Device.prototype.status = function() { Cordova.exec(null, null, "TCPlugin", "deviceStatus", []); } - - // Noops until I figure out why the hell using sounds in Phonegap gives EXC_BAD_ACCESS TwilioPlugin.Device.prototype.sounds = { - //incoming: function(boolean) {}, - //outgoing: function(boolean) {}, - //disconnect: function(boolean) {} + incoming: function(boolean) {}, + outgoing: function(boolean) {}, + disconnect: function(boolean) {} } @@ -130,6 +128,7 @@ } TwilioPlugin.Connection.prototype.sendDigits = function(string) { + //Cordova.exec("TCPlugin.sendDigits", string); Cordova.exec(null, null, "TCPlugin", "sendDigits", [string]); } From f23f0f39c23b684336572baf9c648678bc8560fa Mon Sep 17 00:00:00 2001 From: Lyle Pratt Date: Fri, 2 Aug 2013 14:57:03 -0500 Subject: [PATCH 7/7] Fixed issue with intent messing with back button in Android. Changed the notification to use your app's notification.png file. --- .../IncomingConnectionActivity.java | 5 +- .../plugins/twilioclient/TCPlugin.java | 90 ++++++------------- README.md | 1 + 3 files changed, 34 insertions(+), 62 deletions(-) diff --git a/Android/src/com/phonegap/plugins/twilioclient/IncomingConnectionActivity.java b/Android/src/com/phonegap/plugins/twilioclient/IncomingConnectionActivity.java index a6e140c..ad2bdff 100644 --- a/Android/src/com/phonegap/plugins/twilioclient/IncomingConnectionActivity.java +++ b/Android/src/com/phonegap/plugins/twilioclient/IncomingConnectionActivity.java @@ -3,6 +3,7 @@ import android.app.Activity; import android.content.Intent; import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; //import com.twilio.client.Connection; //import com.twilio.client.Device; @@ -19,6 +20,7 @@ public class IncomingConnectionActivity extends Activity { @Override public void onNewIntent(Intent intent) { + Log.d("TCPlugin", "ON NEW INTENT IN CONNECTION ACTIVITY"); super.onNewIntent(intent); setIntent(intent); } @@ -26,12 +28,13 @@ public void onNewIntent(Intent intent) @Override public void onResume() { + Log.d("TCPlugin", "ON RESUME IN CONNECTION ACTIVITY"); super.onResume(); Intent intent = getIntent(); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); intent.setAction(ACTION_NAME); lbm.sendBroadcast(intent); - + finish(); } diff --git a/Android/src/com/phonegap/plugins/twilioclient/TCPlugin.java b/Android/src/com/phonegap/plugins/twilioclient/TCPlugin.java index 3d0f439..762c973 100644 --- a/Android/src/com/phonegap/plugins/twilioclient/TCPlugin.java +++ b/Android/src/com/phonegap/plugins/twilioclient/TCPlugin.java @@ -12,7 +12,7 @@ import org.json.JSONException; import org.json.JSONObject; -import android.R; +//import android.R; import android.app.Activity; import android.app.NotificationManager; import android.app.PendingIntent; @@ -26,6 +26,7 @@ import android.support.v4.content.LocalBroadcastManager; import android.util.Log; + import com.twilio.client.Connection; import com.twilio.client.ConnectionListener; import com.twilio.client.Device; @@ -55,6 +56,7 @@ public class TCPlugin extends CordovaPlugin implements DeviceListener, private JSONArray mInitDeviceSetupArgs; private int mCurrentNotificationId = 1; private String mCurrentNotificationText; + private TCPlugin plugin = this; @@ -63,39 +65,13 @@ public class TCPlugin extends CordovaPlugin implements DeviceListener, public void onReceive(Context context, Intent intent) { // mDevice = intent.getParcelableExtra(Device.EXTRA_DEVICE); mConnection = intent.getParcelableExtra(Device.EXTRA_CONNECTION); - Log.d(TAG, "incoming intent received with connection: " - + mConnection.getState().name()); + mConnection.setConnectionListener(plugin); + Log.d(TAG, "incoming intent received with connection: "+ mConnection.getState().name()); JSONObject connection = new JSONObject(); - try { - connection.putOpt("parameters", getJSONObject(mConnection.getParameters())); - - if (mCurrentNotificationText != null) { - - /* - PackageManager pm = context.getPackageManager(); - Intent notificationIntent = pm.getLaunchIntentForPackage(context.getPackageName()); - notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - - PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0); - - NotificationCompat.Builder mBuilder = - new NotificationCompat.Builder(context) - .setSmallIcon(R.drawable.btn_star_big_on) - .setContentTitle("Answer") - .setContentText(mCurrentNotificationText) - .setContentIntent(pendingIntent); - // Gets an instance of the NotificationManager service - NotificationManager mNotifyMgr = - (NotificationManager) TCPlugin.this.webView.getContext().getSystemService(Activity.NOTIFICATION_SERVICE); - // Builds the notification and issues it. - mNotifyMgr.notify(mCurrentNotificationId, mBuilder.build()); - */ - } - - } catch (JSONException e) { - Log.e(TAG,e.getLocalizedMessage(), e); + String constate = mConnection.getState().name(); + if(constate.equals("PENDING")) { + TCPlugin.this.javascriptCallback("onincoming", connection, mInitCallbackContext); } - TCPlugin.this.javascriptCallback("onincoming", connection, mInitCallbackContext); } }; @@ -194,21 +170,13 @@ private void deviceSetup(JSONArray arguments, } mDevice = Twilio.createDevice(arguments.optString(0), this); - // handle incoming phone requests - // 1) configure Twilio - Intent intent = new Intent(this.cordova.getActivity(), - IncomingConnectionActivity.class); - PendingIntent pendingIntent = PendingIntent.getActivity( - this.cordova.getActivity(), 0, intent, - PendingIntent.FLAG_UPDATE_CURRENT); + Intent intent = new Intent(this.cordova.getActivity(), IncomingConnectionActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(this.cordova.getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); mDevice.setIncomingIntent(pendingIntent); - // 2) configure the local broadcast manager - LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(cordova - .getActivity()); - lbm.registerReceiver(mBroadcastReceiver, new IntentFilter( - IncomingConnectionActivity.ACTION_NAME)); + + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(cordova.getActivity()); + lbm.registerReceiver(mBroadcastReceiver, new IntentFilter(IncomingConnectionActivity.ACTION_NAME)); javascriptCallback("onready", callbackContext); - } private void connect(JSONArray arguments, CallbackContext callbackContext) { @@ -347,27 +315,28 @@ private void connectionStatus(CallbackContext callbackContext) { private void showNotification(JSONArray arguments, CallbackContext context) { + Context acontext = TCPlugin.this.webView.getContext(); NotificationManager mNotifyMgr = - (NotificationManager) TCPlugin.this.webView.getContext().getSystemService(Activity.NOTIFICATION_SERVICE); + (NotificationManager) acontext.getSystemService(Activity.NOTIFICATION_SERVICE); mNotifyMgr.cancelAll(); - mCurrentNotificationText = arguments.optString(0); + mCurrentNotificationText = arguments.optString(0); + - Context acontext = TCPlugin.this.webView.getContext(); PackageManager pm = acontext.getPackageManager(); Intent notificationIntent = pm.getLaunchIntentForPackage(acontext.getPackageName()); - notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + notificationIntent.putExtra("notificationTag", "BVNotification"); PendingIntent pendingIntent = PendingIntent.getActivity(acontext, 0, notificationIntent, 0); - + int notification_icon = acontext.getResources().getIdentifier("notification", "drawable", acontext.getPackageName()); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(acontext) - .setSmallIcon(R.drawable.btn_star_big_on) - .setContentTitle("Answer") + .setSmallIcon(notification_icon) + .setContentTitle("Incoming Call") .setContentText(mCurrentNotificationText) .setContentIntent(pendingIntent); mNotifyMgr.notify(mCurrentNotificationId, mBuilder.build()); - context.success(); } @@ -421,20 +390,20 @@ public void onPresenceChanged(Device device, PresenceEvent presenceEvent) { @Override public void onStartListening(Device device) { // What to do here? The JS library doesn't have an event for this. - + } @Override public void onStopListening(Device device) { // TODO Auto-generated method stub - + Log.d(TAG, "onStopListening"); } @Override public void onStopListening(Device device, int errorCode, String errorMessage) { // this.javascriptErrorback(errorCode, errorMessage); - + Log.d(TAG, "onStopListeningWithError"); } @Override @@ -457,7 +426,7 @@ public void onInitialized() { // Twilio Connection Listener methods @Override - public void onConnected(Connection connection) { + public void onConnected(Connection connection) { Log.d(TAG, "onConnected()"); fireDocumentEvent("onconnect"); if (connection.isIncoming()) { @@ -483,8 +452,7 @@ public void onDisconnected(Connection connection) { } @Override - public void onDisconnected(Connection connection, int errorCode, - String errorMessage) { + public void onDisconnected(Connection connection, int errorCode, String errorMessage) { // TODO: Pass error back Log.d(TAG, "onDisconnected(): " + errorMessage); onDisconnected(connection); @@ -516,8 +484,8 @@ private void javascriptCallback(String event, javascriptCallback(event, null, callbackContext); } - private void javascriptErrorback(int errorCode, String errorMessage, - CallbackContext callbackContext) { + + private void javascriptErrorback(int errorCode, String errorMessage, CallbackContext callbackContext) { JSONObject object = new JSONObject(); try { object.putOpt("message", errorMessage); diff --git a/README.md b/README.md index 280873e..d32cfee 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ These are Phonegap plugins that expose the same JS API as Twilio Client for web ``` - Add tcPlugin.js to your application's www folder (in the assets directory) +- You need to add a notification.png file to your applications res/drawable-ldpi, res/drawable-mdpi & res/drawable-hdpi or res/drawable-xhdpi directories (depending on what resolutions you want to support). - Copy the two plugin .java files into your application's src folder, keeping the com/phonegap/plugins/twilioclient directory structure - Last, add the plugin to config.xml (in res/xml)