"&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&Q.test(i)&&m.insertBefore(b.createTextNode(Q.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bb=/alpha\([^)]*\)/i,bc=/opacity=([^)]*)/,bd=/-([a-z])/ig,be=/([A-Z])/g,bf=/^-?\d+(?:px)?$/i,bg=/^-?\d/,bh={position:"absolute",visibility:"hidden",display:"block"},bi=["Left","Right"],bj=["Top","Bottom"],bk,bl,bm,bn=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bk(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bk)return bk(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bd,bn)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bo(a,b,e):d.swap(a,bh,function(){f=bo(a,b,e)});if(f<=0){f=bk(a,b,b),f==="0px"&&bm&&(f=bm(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bf.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return bc.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bb.test(f)?f.replace(bb,e):c.filter+" "+e}}),c.defaultView&&c.defaultView.getComputedStyle&&(bl=function(a,c,e){var f,g,h;e=e.replace(be,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bm=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bf.test(d)&&bg.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bk=bl||bm,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var bp=/%20/g,bq=/\[\]$/,br=/\r?\n/g,bs=/#.*$/,bt=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bu=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bv=/(?:^file|^widget|\-extension):$/,bw=/^(?:GET|HEAD)$/,bx=/^\/\//,by=/\?/,bz=/
-```
-
-### Manual Installation for iOS
-
-Copy the following files to your project's Plugins folder:
-
-```
-AppDelegate+notification.h
-AppDelegate+notification.m
-PushPlugin.h
-PushPlugin.m
-```
-
-Add a reference for this plugin to the plugins section in `config.xml`:
-
-```xml
-
-
-
-```
-
-Add the `PushNotification.js` script to your assets/www folder (or javascripts folder, wherever you want really) and reference it in your main index.html file.
-
-```html
-
-```
-
-### Manual Installation for WP8
-
-Copy the following files to your project's Commands folder and add it to the VS project:
-
-```
-PushPlugin.cs
-```
-
-Add a reference to this plugin in `config.xml`:
-
-```xml
-
-
-
-```
-
-Add the `PushNotification.js` script to your assets/www folder (or javascripts folder, wherever you want really) and reference it in your main index.html file.
-```html
-
-```
-
-Do not forget to reference the `cordova.js` as well.
-
-
-
-In your Visual Studio project add reference to the `Newtonsoft.Json.dll` as well - it is needed for serialization and deserialization of the objects.
-
-Also you need to enable the **"ID_CAP_PUSH_NOTIFICATION"** capability in **Properties->WMAppManifest.xml** of your project.
-
-### Manual Installation for Windows8
-
-Add the `src/windows8/PushPluginProxy.js` script to your `www` folder and reference it in your main index.html file.
-```html
-
-```
-
-Do not forget to reference the `cordova.js` as well.
-
-
-
-To receive toast notifications additional [toastCapable=’true’](http://msdn.microsoft.com/en-us/library/windows/apps/hh781238.aspx) attribute is required to be manually added in manifest file.
-
-
-
-##Automatic Installation
-
-Below are the methods for installing this plugin automatically using command line tools. For additional info, take a look at the [Plugman Documentation](https://github.com/apache/cordova-plugman/blob/master/README.md) and [Cordova Plugin Specification](https://github.com/alunny/cordova-plugin-spec).
-
-**Note:** For each service supported - ADM, APNS, GCM or MPNS - you may need to download the SDK and other support files. See the [Manual Installation](#manual_installation) instructions below for more details about each platform.
-
-### Cordova
-
-The plugin can be installed via the Cordova command line interface:
-
-1) Navigate to the root folder for your phonegap project. 2) Run the command.
-
-```sh
-cordova plugin add https://github.com/phonegap-build/PushPlugin.git
-```
-
-### Phonegap
-
-The plugin can be installed using the Phonegap command line interface:
-
-1) Navigate to the root folder for your phonegap project. 2) Run the command.
-
-```sh
-phonegap local plugin add https://github.com/phonegap-build/PushPlugin.git
-```
-
-### Plugman
-
-The plugin is based on [plugman](https://github.com/apache/cordova-plugman) and can be installed using the Plugman command line interface:
-
-```sh
-plugman install --platform [PLATFORM] --project [TARGET-PATH] --plugin [PLUGIN-PATH]
-
-where
- [PLATFORM] = ios, amazon-fireos, android, wp8, windows8 or blackberry10
- [TARGET-PATH] = path to folder containing your phonegap project
- [PLUGIN-PATH] = path to folder containing this plugin
-```
-
-
-
-
-
-## Plugin API
-
-In the plugin `examples` folder you will find a sample implementation showing how to interact with the PushPlugin. Modify it to suit your needs.
-
-#### pushNotification
-The plugin instance variable.
-
-```js
-var pushNotification;
-
-document.addEventListener("deviceready", function(){
- pushNotification = window.plugins.pushNotification;
- ...
-});
-```
-
-#### register
-To be called as soon as the device becomes ready.
-
-```js
-$("#app-status-ul").append('
registering ' + device.platform + '
');
-if ( device.platform == 'android' || device.platform == 'Android' || device.platform == "amazon-fireos" ){
- pushNotification.register(
- successHandler,
- errorHandler,
- {
- "senderID":"replace_with_sender_id",
- "ecb":"onNotification"
- });
-} else if ( device.platform == 'blackberry10'){
- pushNotification.register(
- successHandler,
- errorHandler,
- {
- invokeTargetId : "replace_with_invoke_target_id",
- appId: "replace_with_app_id",
- ppgUrl:"replace_with_ppg_url", //remove for BES pushes
- ecb: "pushNotificationHandler",
- simChangeCallback: replace_with_simChange_callback,
- pushTransportReadyCallback: replace_with_pushTransportReady_callback,
- launchApplicationOnPush: true
- });
-} else {
- pushNotification.register(
- tokenHandler,
- errorHandler,
- {
- "badge":"true",
- "sound":"true",
- "alert":"true",
- "ecb":"onNotificationAPN"
- });
-}
-```
-
-On success, you will get a call to tokenHandler (iOS), onNotification (Android and Amazon Fire OS), onNotificationWP8 (WP8) or successHandler (Blackberry10), allowing you to obtain the device token or registration ID, or push channel name and Uri respectively. Those values will typically get posted to your intermediary push server so it knows who it can send notifications to.
-
-***Note***
-
-- **Amazon Fire OS**: "ecb" MUST be provided in order to get callback notifications. If you have not already registered with Amazon developer portal,you will have to obtain credentials and api_key for your app. This is described more in detail in the [Registering your app for Amazon Device Messaging (ADM)](#registering_for_adm) section below.
-
-- **Android**: If you have not already done so, you'll need to set up a Google API project, to generate your senderID. [Follow these steps](http://developer.android.com/guide/google/gcm/gs.html) to do so. This is described more fully in the **Testing** section below. In this example, be sure and substitute your own senderID. Get your senderID by signing into to your [google dashboard](https://code.google.com/apis/console/). The senderID is found at *Overview->Dashboard->Project Number*.
-
-- **BlackBerry10**: "ecb" MUST be provided to get notified of incoming push notifications. Also note, if doing a public consumer (BIS) push, you need to manually add the _sys_use_consumer_push permission to config.xml. `_sys_use_consumer_push`. In order to receieve notifications, an invoke target must be [setup](http://developer.blackberry.com/html5/documentation/v2_1/rim_invoke-target.html) for push. See [BlackBerry Push Service](http://developer.blackberry.com/html5/apis/v2_1/blackberry.push.pushservice.html) for additional information about blackberry push options.
-
-
-
-
-#### successHandler
-Called when a plugin method returns without error
-
-```js
-// result contains any message sent from the plugin call
-function successHandler (result) {
- alert('result = ' + result);
-}
-```
-
-#### errorHandler
-Called when the plugin returns an error
-
-```js
-// result contains any error description text returned from the plugin call
-function errorHandler (error) {
- alert('error = ' + error);
-}
-```
-
-#### ecb (Amazon Fire OS, Android and iOS)
-Event callback that gets called when your device receives a notification
-
-```js
-// iOS
-function onNotificationAPN (event) {
- if ( event.alert )
- {
- navigator.notification.alert(event.alert);
- }
-
- if ( event.sound )
- {
- var snd = new Media(event.sound);
- snd.play();
- }
-
- if ( event.badge )
- {
- pushNotification.setApplicationIconBadgeNumber(successHandler, errorHandler, event.badge);
- }
-}
-```
-
-```js
-// Android and Amazon Fire OS
-function onNotification(e) {
- $("#app-status-ul").append('
");
- // Your GCM push server needs to know the regID before it can push to this device
- // here is where you might want to send it the regID for later use.
- console.log("regID = " + e.regid);
- }
- break;
-
- case 'message':
- // if this flag is set, this notification happened while we were in the foreground.
- // you might want to play a sound to get the user's attention, throw up a dialog, etc.
- if ( e.foreground )
- {
- $("#app-status-ul").append('
--INLINE NOTIFICATION--' + '
');
-
- // on Android soundname is outside the payload.
- // On Amazon FireOS all custom attributes are contained within payload
- var soundfile = e.soundname || e.payload.sound;
- // if the notification contains a soundname, play it.
- var my_media = new Media("/android_asset/www/"+ soundfile);
- my_media.play();
- }
- else
- { // otherwise we were launched because the user touched a notification in the notification tray.
- if ( e.coldstart )
- {
- $("#app-status-ul").append('
--COLDSTART NOTIFICATION--' + '
');
- }
- else
- {
- $("#app-status-ul").append('
--BACKGROUND NOTIFICATION--' + '
');
- }
- }
-
- $("#app-status-ul").append('
MESSAGE -> MSG: ' + e.payload.message + '
');
- //Only works for GCM
- $("#app-status-ul").append('
MESSAGE -> MSGCNT: ' + e.payload.msgcnt + '
');
- //Only works on Amazon Fire OS
- $status.append('
MESSAGE -> TIME: ' + e.payload.timeStamp + '
');
- break;
-
- case 'error':
- $("#app-status-ul").append('
EVENT -> Unknown, an event was received and we do not know what it is
');
- break;
- }
-}
-```
-
-```js
-// BlackBerry10
-function pushNotificationHandler(pushpayload) {
- var contentType = pushpayload.headers["Content-Type"],
- id = pushpayload.id,
- data = pushpayload.data;//blob
-
- // If an acknowledgement of the push is required (that is, the push was sent as a confirmed push
- // - which is equivalent terminology to the push being sent with application level reliability),
- // then you must either accept the push or reject the push
- if (pushpayload.isAcknowledgeRequired) {
- // In our sample, we always accept the push, but situations might arise where an application
- // might want to reject the push (for example, after looking at the headers that came with the push
- // or the data of the push, we might decide that the push received did not match what we expected
- // and so we might want to reject it)
- pushpayload.acknowledge(true);
- }
-};
-```
-
-Looking at the above message handling code for Android/Amazon Fire OS, a few things bear explanation. Your app may receive a notification while it is active (INLINE). If you background the app by hitting the Home button on your device, you may later receive a status bar notification. Selecting that notification from the status will bring your app to the front and allow you to process the notification (BACKGROUND). Finally, should you completely exit the app by hitting the back button from the home page, you may still receive a notification. Touching that notification in the notification tray will relaunch your app and allow you to process the notification (COLDSTART). In this case the **coldstart** flag will be set on the incoming event. You can look at the **foreground** flag on the event to determine whether you are processing a background or an in-line notification. You may choose, for example to play a sound or show a dialog only for inline or coldstart notifications since the user has already been alerted via the status bar.
-
-For Amazon Fire OS, offline message can also be received when app is launched via carousel or by tapping on app icon from apps. In either case once app delivers the offline message to JS, notification will be cleared.
-
-Since the Android and Amazon Fire OS notification data models are much more flexible than that of iOS, there may be additional elements beyond **message**. You can access those elements and any additional ones via the **payload** element. This means that if your data model should change in the future, there will be no need to change and recompile the plugin.
-
-
-
-#### senderID (Android only)
-This is the Google project ID you need to obtain by [registering your application](http://developer.android.com/guide/google/gcm/gs.html) for GCM
-
-
-#### tokenHandler (iOS only)
-Called when the device has registered with a unique device token.
-
-```js
-function tokenHandler (result) {
- // Your iOS push server needs to know the token before it can push to this device
- // here is where you might want to send it the token for later use.
- alert('device token = ' + result);
-}
-```
-
-#### setApplicationIconBadgeNumber (iOS only)
-Set the badge count visible when the app is not running
-
-```js
-pushNotification.setApplicationIconBadgeNumber(successCallback, errorCallback, badgeCount);
-```
-
-The `badgeCount` is an integer indicating what number should show up in the badge. Passing 0 will clear the badge.
-
-#### unregister (Amazon Fire OS, Android and iOS)
-You will typically call this when your app is exiting, to cleanup any used resources. Its not strictly necessary to call it, and indeed it may be desireable to NOT call it if you are debugging your intermediarry push server. When you call unregister(), the current token for a particular device will get invalidated, and the next call to register() will return a new token. If you do NOT call unregister(), the last token will remain in effect until it is invalidated for some reason at the GCM/ADM side. Since such invalidations are beyond your control, its recommended that, in a production environment, that you have a matching unregister() call, for every call to register(), and that your server updates the devices' records each time.
-
-```js
-pushNotification.unregister(successHandler, errorHandler, options);
-```
-
-
-### WP8
-
-#### register (WP8 Only)
-
-```js
-
-if(device.platform == "Win32NT"){
- pushNotification.register(
- channelHandler,
- errorHandler,
- {
- "channelName": channelName,
- "ecb": "onNotificationWP8",
- "uccb": "channelHandler",
- "errcb": "jsonErrorHandler"
- });
-}
-
-```
-
-#### channelHandler (WP8 only)
-Called after a push notification channel is opened and push notification URI is returned. [The application is now set to receive notifications.](http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202940(v=vs.105).aspx)
-
-
-#### ecb (WP8 Only)
-Event callback that gets called when your device receives a notification. This is fired if the app is running when you receive the toast notification, or raw notification.
-
-```js
-//handle MPNS notifications for WP8
-function onNotificationWP8(e) {
-
- if (e.type == "toast" && e.jsonContent) {
- pushNotification.showToastNotification(successHandler, errorHandler,
- {
- "Title": e.jsonContent["wp:Text1"], "Subtitle": e.jsonContent["wp:Text2"], "NavigationUri": e.jsonContent["wp:Param"]
- });
- }
-
- if (e.type == "raw" && e.jsonContent) {
- alert(e.jsonContent.Body);
- }
-}
-```
-
-#### uccb (WP8 only)
-Event callback that gets called when the channel you have opened gets its Uri updated. This function is needed in case the MPNS updates the opened channel Uri. This function will take care of showing updated Uri.
-
-
-#### errcb (WP8 only)
-Event callback that gets called when server error occurs when receiving notification from the MPNS server (for example invalid format of the notification).
-
-```js
-function jsonErrorHandler(error) {
- $("#app-status-ul").append('
error:' + error.code + '
');
- $("#app-status-ul").append('
error:' + error.message + '
');
- }
-```
-
-#### showToastNotification (WP8 only)
-Show toast notification if app is deactivated.
-
- pushNotification.showToastNotification(successCallback, errorCallback, options);
-
-The toast notification's properties are set explicitly using json. They can be get in onNotificationWP8 and used for whatever purposes needed.
-
-
-To control the launch page when the user taps on your toast notification when the app is not running, add the following code to your mainpage.xaml.cs
-```cs
-protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
-{
- base.OnNavigatedTo(e);
- try
- {
- if (this.NavigationContext.QueryString["NavigatedFrom"] == "toast") // this is set on the server
- {
- this.PGView.StartPageUri = new Uri("//www/index.html#notification-page", UriKind.Relative);
- }
- }
- catch (KeyNotFoundException)
- {
- }
-}
-```
-Or you can add another `Page2.xaml` just for testing toast navigate url. Like the [MSDN Toast Sample](http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202967(v=vs.105).aspx)
-
-To test the tile notification, you will need to add tile images like the [MSDN Tile Sample](http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202970(v=vs.105).aspx#BKMK_CreatingaPushClienttoReceiveTileNotifications)
-
-#### unregister (WP8 Only)
-
-When using the plugin for wp8 you will need to unregister the push channel you have register in case you would want to open another one. You need to know the name of the channel you have opened in order to close it. Please keep in mind that one application can have only one opened channel at time and in order to open another you will have to close any already opened channel.
-
-```cs
-function unregister() {
- var channelName = $("#channel-btn").val();
- pushNotification.unregister(
- successHandler, errorHandler,
- {
- "channelName": channelName
- });
-}
-```
-
-You'll probably want to trap on the **backbutton** event and only call this when the home page is showing. Remember, the back button on android is not the same as the Home button. When you hit the back button from the home page, your activity gets dismissed. Here is an example of how to trap the backbutton event;
-
-```js
-function onDeviceReady() {
- $("#app-status-ul").append('
');
-
- if( $("#home").length > 0 )
- {
- e.preventDefault();
- pushNotification.unregister(successHandler, errorHandler);
- navigator.app.exitApp();
- }
- else
- {
- navigator.app.backHistory();
- }
- }, false);
-
- // additional onDeviceReady work...
-}
-```
-
-For the above to work, make sure the content for your home page is wrapped in an element with an id of home, like this;
-
-```html
-
-
-
-
Cordova PushNotification Plugin Demo
-
-
-
-```
-
-### windows8
-Sample usage is showed below. **Note**. To be able to receive toast notifications additional [toastCapable=’true’](http://msdn.microsoft.com/en-us/library/windows/apps/hh781238.aspx) attribute is required in manifest file.
-
-```js
-// fired when push notification is received
-window.onNotification = function (e) {
- navigator.notification.alert('Notification received: ' + JSON.stringify(e));
-}
-var pushNotification = window.plugins.pushNotification;
-pushNotification.register(successHandler, errorHandler, {"channelName":"your_channel_name","ecb":"onNotification"});
-
-function successHandler(result) {
- console.log('registered###' + result.uri);
- // send uri to your notification server
-}
-function errorHandler(error) {
- console.log('error###' + error);
-}
-```
-See [Sending push notifications with WNS](http://msdn.microsoft.com/en-us/library/windows/apps/hh465460.aspx) to send test push notification.
-
-
-
-## Testing
-The notification system consists of several interdependent components.
-
-1. The client application which runs on a device and receives notifications.
-2. The notification service provider (ADM for Amazon Fire OS, APNS for Apple, GCM for Google, MPNS for WP8)
-3. Intermediary servers that collect device IDs from clients and push notifications through ADM, APNS GCM or MPNS.
-
-This plugin and its target Cordova application comprise the client application.The ADM, APNS, GCM and MPNS infrastructure are maintained by Amazon, Apple, Google and Microsoft, respectively. In order to send push notifications to your users, you would typically run an intermediary server or employ a 3rd party push service. This is true for all ADM (Amazon), APNS (iOS), GCM (Android) and MPNS (WP8) notifications. However, when testing the notification client applications, it may be desirable to be able to push notifications directly from your desktop, without having to design and build those server's first. There are a number of solutions out there to allow you to push from a desktop machine, sans server.
-
-### Testing APNS and GCM notifications
-
-An easy solution to test APNS and GCM is a ruby gem called [pushmeup](http://rubygems.org/gems/pushmeup) (tested only on Mac, but it probably works fine on Windows as well).
-
-#### Prerequisites:
-
-- Ruby gems is installed and working.
-- You have successfully built a client with this plugin, on both iOS and Android and have installed them on a device.
-- You have installed the [PushMeUp gem](https://github.com/NicosKaralis/pushmeup): `$ sudo gem install pushmeup`
-
-
-
-#### APNS/iOS Setup
-[Follow this tutorial](http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12) to create a file called ck.pem.
-
-Start at the section entitled "Generating the Certificate Signing Request (CSR)", and substitute your own Bundle Identifier, and Description.
-
-1. Go the this plugin's Example/server folder and open pushAPNS.rb in the text editor of your choice.
-2. Set the APNS.pem variable to the path of the ck.pem file you just created
-3. Set APNS.pass to the password associated with the certificate you just created. (warning this is cleartext, so don't share this file)
-4. Set device_token to the token for the device you want to send a push to. (you can run the Cordova app / plugin in Xcode and extract the token from the log messages)
-5. Save your changes.
-
-
-#### Android/GCM Setup
-[Follow these steps](http://developer.android.com/guide/google/gcm/gs.html) to generate a project ID and a server based API key.
-
-1. Go the this plugin's Example/server folder and open pushGCM.rb in the text editor of your choice.
-2. Set the GCM.key variable to the API key you just generated.
-3. Set the destination variable to the Registration ID of the device. (you can run the Cordova app / plugin in on a device via Eclipse and extract the regID from the log messages)
-
-#### Sending a test notification
-
-1. cd to the directory containing the two .rb files we just edited.
-2. Run the Cordova app / plugin on both the Android and iOS devices you used to obtain the regID / device token, respectively.
-3. `$ ruby pushGCM.rb` or `$ ruby pushAPNS.rb`
-
-If you run this demo using the emulator you will not receive notifications from GCM. You need to run it on an actual device to receive messages or install the proper libraries on your emulator (You can follow [this guide](http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/) under the section titled "Installing helper libraries and setting up the Emulator") If everything seems right and you are not receiving a registration id response back from Google, try uninstalling and reinstalling your app. That has worked for some devs out there.
-
-While the data model for iOS is somewhat fixed, it should be noted that GCM is far more flexible. The Android implementation in this plugin, for example, assumes the incoming message will contain a '**message**' and a '**msgcnt**' node. This is reflected in both the plugin (see GCMIntentService.java) as well as in provided example ruby script (pushGCM.rb). Should you employ a commercial service, their data model may differ. As mentioned earlier, this is where you will want to take a look at the **payload** element of the message event. In addition to the cannonical message and msgcnt elements, any additional elements in the incoming JSON object will be accessible here, obviating the need to edit and recompile the plugin. Many thanks to Tobias Hößl for this functionality!
-
-### Testing ADM Notifications for Amazon Fire OS
-
-####Register your app for Amazon Device Messaging (ADM)
-
-1. Create a developer account on [Amazon Developer Portal](https://developer.amazon.com/home.html)
-2. [Add a new app](https://developer.amazon.com/application/new.html) and turn Device Messaging switch to ON. Create a sample app for your device so you have the app name and package name used to register online.
-3. Create [Security Profile](https://developer.amazon.com/iba-sp/overview.html) and obtain [ADM credentials](https://developer.amazon.com/sdk/adm/credentials.html) for your app.
-
-#### Sending a test notification
-
-1. Inside the plugin's examples/server folder, open the `pushADM.js` NodeJS script with a text editor. (You should already have NodeJS installed).
-2. Edit the CLIENT_ID and CLIENT_SECRET variables with the values from the ADM Security Profile page for your app. This will allow your app to securely identify itself to Amazon services.
-3. Compile and run the sample app on your device. Note the sample app requires the Cordova Device and Media plugins to work.
-4. The sample app will display your device's registration ID. Copy that value (it's very long) from your device into `pushADM.js`, entered in the REGISTRATION_IDS array. To test sending messages to more than one device, you can enter in multiple REGISTRATION_IDS into the array.
-5. To send a test push notification, run the test script via a command line using NodeJS: `$ node pushADM.js`.
-
-
-### Testing MPNS Notification for WP8
-The simplest way to test the plugin is to create an ASP.NET webpage that sends different notifications by using the URI that is returned when the push channel is created on the device.
-
-You can see how to create one from MSDN Samples:
-
-- [Send Toast Notifications (MSDN Sample)](http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202967(v=vs.105).aspx#BKMK_SendingaToastNotification)
-- [Send Tile Notification (MSDN Sample)](http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202970(v=vs.105).aspx#BKMK_SendingaTileNotification)
-- [Send Raw Notification (MSDN Sample)](http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202977(v=vs.105).aspx#BKMK_RunningtheRawNotificationSample)
-
-
-### Sending push notifications on BlackBerry10
-If doing a BES push, ensure the device has been enterprise activated, has network access (wifi or sim) and your app is installed in the work permiter. You also need to make sure the _sys_use_consumer_push permission is NOT specified in the config.xml. This permission is meant only for public consumer BIS pushes and will cause an error when registering.
-
-If doing a public consumer BIS push, please ensure the _sys_use_consumer_push permission is added to the config.xml.
-
-Both types of pushes require the use of a Push Initiator.
-
-- [App based BIS Initiator](https://github.com/blackberry/BB10-WebWorks-Samples/tree/master/pushCaptureBasics/pushInitiator)
-- [Web based BIS Initiator (Push Service SDK)](https://developer.blackberry.com/services/push/)
-- [Web based BES Initiator](https://github.com/blackberry/BES10-WebWorks/tree/master/SimplePushTest/WW2.0/server)
-
-For additional information on BlackBerry Push see https://developer.blackberry.com/services/push/.
-
-### Troubleshooting and next steps
-If all went well, you should see a notification show up on each device. If not, make sure you are not being blocked by a firewall, and that you have internet access. Check and recheck the token id, the registration ID and the certificate generating process.
-
-In a production environment, your app, upon registration, would send the device id (iOS) or the registration id (Android/Amazon), to your intermediary push server. For iOS, the push certificate would also be stored there, and would be used to authenticate push requests to the APNS server. When a push request is processed, this information is then used to target specific apps running on individual devices.
-
-If you're not up to building and maintaining your own intermediary push server, there are a number of commercial push services out there which support both APNS and GCM.
-
-- [Amazon Simple Notification Service](https://aws.amazon.com/sns/)
-- [kony](http://www.kony.com/push-notification-services)
-- [openpush](http://openpush.im)
-- [Pushwoosh](http://www.pushwoosh.com/)
-- [Urban Airship](http://urbanairship.com/products/push-notifications/)
-- etc.
-
-
-
-
-##Additional Resources
-
-- [Amazon Device Messaging](https://developer.amazon.com/sdk/adm/credentials.html)
-- [Apple Push Notification Services Tutorial: Part 1/2](http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12)
-- [Apple Push Notification Services Tutorial: Part 2/2](http://www.raywenderlich.com/3525/apple-push-notification-services-tutorial-part-2)
-- [Google Cloud Messaging for Android](http://developer.android.com/guide/google/gcm/index.html) (Android)
-- [How to Implement Push Notifications for Android](http://tokudu.com/2010/how-to-implement-push-notifications-for-android/)
-- [Local and Push Notification Programming Guide](http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ApplePushService/ApplePushService.html) (Apple)
-
-
-## Acknowledgments
-
-Huge thanks to Mark Nutter whose [GCM-Cordova plugin](https://github.com/marknutter/GCM-Cordova) forms the basis for the Android side implimentation.
-
-Likewise, the iOS side was inspired by Olivier Louvignes' [Cordova PushNotification Plugin](https://github.com/phonegap/phonegap-plugins/tree/master/iOS/PushNotification) (Copyright (c) 2012 Olivier Louvignes) for iOS.
-
-Props to [Tobias Hößl](https://github.com/CatoTH), who provided the code to surface the full JSON object up to the JS layer.
diff --git a/plugin.xml b/plugin.xml
index 68a46ff3..ab6fd9b1 100755
--- a/plugin.xml
+++ b/plugin.xml
@@ -1,167 +1,118 @@
+ id="com.schneider-electric.wisersmart.plugins.PushPlugin"
+ version="0.0.3">
PushPluginBob Easterday
-
+ https://github.com/Schneider-Electric-Wiser/PushNotification
+
+ BASED ON 2.5.0
This plugin allows your application to receive push notifications on Android, iOS, WP8 and Windows8 devices.
Android uses Google Cloud Messaging.
iOS uses Apple APNS Notifications.
WP8 uses Microsoft MPNS Notifications.
Windows8 uses Microsoft WNS Notifications.
+copied from:
+ https://github.com/Telerik-Verified-Plugins/PushNotification
MIT
-
+
-
+
+
+
+
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/android/com/plugin/android-support-v13.jar b/src/android/com/plugin/android-support-v13.jar
index cd47212b..eb5eca3d 100644
Binary files a/src/android/com/plugin/android-support-v13.jar and b/src/android/com/plugin/android-support-v13.jar differ
diff --git a/src/android/com/plugin/gcm/CordovaGCMBroadcastReceiver.java b/src/android/com/plugin/gcm/CordovaGCMBroadcastReceiver.java
index e383f846..4c4ea7b0 100644
--- a/src/android/com/plugin/gcm/CordovaGCMBroadcastReceiver.java
+++ b/src/android/com/plugin/gcm/CordovaGCMBroadcastReceiver.java
@@ -1,19 +1,150 @@
package com.plugin.gcm;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.content.WakefulBroadcastReceiver;
+import android.util.Log;
+import com.google.android.gms.gcm.GoogleCloudMessaging;
+import org.json.JSONException;
+import org.json.JSONObject;
-import com.google.android.gcm.GCMBroadcastReceiver;
-import static com.google.android.gcm.GCMConstants.DEFAULT_INTENT_SERVICE_CLASS_NAME;
+import java.util.Random;
/*
* Implementation of GCMBroadcastReceiver that hard-wires the intent service to be
- * com.plugin.gcm.GCMIntentService, instead of your_package.GCMIntentService
+ * com.plugin.gcm.GcmntentService, instead of your_package.GcmIntentService
*/
-public class CordovaGCMBroadcastReceiver extends GCMBroadcastReceiver {
-
+public class CordovaGCMBroadcastReceiver extends WakefulBroadcastReceiver {
+ private static final String TAG = "GcmIntentService";
+
@Override
- protected String getGCMIntentServiceClassName(Context context) {
- return "com.plugin.gcm" + DEFAULT_INTENT_SERVICE_CLASS_NAME;
- }
-
+ public void onReceive(Context context, Intent intent) {
+
+ Log.d(TAG, "onHandleIntent - context: " + context);
+
+ // Extract the payload from the message
+ Bundle extras = intent.getExtras();
+ GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
+ String messageType = gcm.getMessageType(intent);
+
+ if (extras != null) {
+ try {
+ if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
+ JSONObject json = new JSONObject();
+
+ json.put("event", "error");
+ json.put("message", extras.toString());
+ PushPlugin.sendJavascript(json);
+ } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
+ JSONObject json = new JSONObject();
+ json.put("event", "deleted");
+ json.put("message", extras.toString());
+ PushPlugin.sendJavascript(json);
+ } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
+ // if we are in the foreground, just surface the payload, else post it to the statusbar
+ if (PushPlugin.isInForeground()) {
+ extras.putBoolean("foreground", true);
+ PushPlugin.sendExtras(extras);
+ } else {
+ extras.putBoolean("foreground", false);
+
+ // Send a notification if there is a message
+ if (extras.getString("message") != null && extras.getString("message").length() != 0) {
+ createNotification(context, extras);
+ }
+ }
+ }
+ } catch (JSONException exception) {
+ Log.d(TAG, "JSON Exception was had!");
+ }
+ }
+ }
+
+ public void createNotification(Context context, Bundle extras) {
+ int notId = 0;
+
+ try {
+ notId = Integer.parseInt(extras.getString("notId", "0"));
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Number format exception - Error parsing Notification ID: " + e.getMessage());
+ } catch (Exception e) {
+ Log.e(TAG, "Number format exception - Error parsing Notification ID" + e.getMessage());
+ }
+ if (notId == 0) {
+ // no notId passed, so assume we want to show all notifications, so make it a random number
+ notId = new Random().nextInt(100000);
+ Log.d(TAG, "Generated random notId: " + notId);
+ } else {
+ Log.d(TAG, "Received notId: " + notId);
+ }
+
+
+ NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ String appName = getAppName(context);
+
+ Intent notificationIntent = new Intent(context, PushHandlerActivity.class);
+ notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ notificationIntent.putExtra("pushBundle", extras);
+
+ PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ int defaults = Notification.DEFAULT_ALL;
+
+ if (extras.getString("defaults") != null) {
+ try {
+ defaults = Integer.parseInt(extras.getString("defaults"));
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ NotificationCompat.Builder mBuilder =
+ new NotificationCompat.Builder(context)
+ .setDefaults(defaults)
+ .setSmallIcon(context.getApplicationInfo().icon)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle(extras.getString("title"))
+ .setTicker(extras.getString("title"))
+ .setContentIntent(contentIntent)
+ .setAutoCancel(true);
+
+ String message = extras.getString("message");
+ if (message != null) {
+ mBuilder.setContentText(message);
+ } else {
+ mBuilder.setContentText("");
+ }
+
+ String msgcnt = extras.getString("msgcnt");
+ if (msgcnt != null) {
+ mBuilder.setNumber(Integer.parseInt(msgcnt));
+ }
+
+ String soundName = extras.getString("sound");
+ if (soundName != null) {
+ Resources r = context.getResources();
+ int resourceId = r.getIdentifier(soundName, "raw", context.getPackageName());
+ Uri soundUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + resourceId);
+ mBuilder.setSound(soundUri);
+ defaults &= ~Notification.DEFAULT_SOUND;
+ mBuilder.setDefaults(defaults);
+ }
+
+ mNotificationManager.notify(appName, notId, mBuilder.build());
+ }
+
+ private static String getAppName(Context context) {
+ CharSequence appName =
+ context
+ .getPackageManager()
+ .getApplicationLabel(context.getApplicationInfo());
+
+ return (String) appName;
+ }
}
\ No newline at end of file
diff --git a/src/android/com/plugin/gcm/GCMIntentService.java b/src/android/com/plugin/gcm/GCMIntentService.java
deleted file mode 100644
index caee145e..00000000
--- a/src/android/com/plugin/gcm/GCMIntentService.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package com.plugin.gcm;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.annotation.SuppressLint;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.NotificationCompat;
-import android.util.Log;
-
-import com.google.android.gcm.GCMBaseIntentService;
-
-@SuppressLint("NewApi")
-public class GCMIntentService extends GCMBaseIntentService {
-
- private static final String TAG = "GCMIntentService";
-
- public GCMIntentService() {
- super("GCMIntentService");
- }
-
- @Override
- public void onRegistered(Context context, String regId) {
-
- Log.v(TAG, "onRegistered: "+ regId);
-
- JSONObject json;
-
- try
- {
- json = new JSONObject().put("event", "registered");
- json.put("regid", regId);
-
- Log.v(TAG, "onRegistered: " + json.toString());
-
- // Send this JSON data to the JavaScript application above EVENT should be set to the msg type
- // In this case this is the registration ID
- PushPlugin.sendJavascript( json );
-
- }
- catch( JSONException e)
- {
- // No message to the user is sent, JSON failed
- Log.e(TAG, "onRegistered: JSON exception");
- }
- }
-
- @Override
- public void onUnregistered(Context context, String regId) {
- Log.d(TAG, "onUnregistered - regId: " + regId);
- }
-
- @Override
- protected void onMessage(Context context, Intent intent) {
- Log.d(TAG, "onMessage - context: " + context);
-
- // Extract the payload from the message
- Bundle extras = intent.getExtras();
- if (extras != null)
- {
- // if we are in the foreground, just surface the payload, else post it to the statusbar
- if (PushPlugin.isInForeground()) {
- extras.putBoolean("foreground", true);
- PushPlugin.sendExtras(extras);
- }
- else {
- extras.putBoolean("foreground", false);
-
- // Send a notification if there is a message
- if (extras.getString("message") != null && extras.getString("message").length() != 0) {
- createNotification(context, extras);
- }
- }
- }
- }
-
- public void createNotification(Context context, Bundle extras)
- {
- NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- String appName = getAppName(this);
-
- Intent notificationIntent = new Intent(this, PushHandlerActivity.class);
- notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- notificationIntent.putExtra("pushBundle", extras);
-
- PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- int defaults = Notification.DEFAULT_ALL;
-
- if (extras.getString("defaults") != null) {
- try {
- defaults = Integer.parseInt(extras.getString("defaults"));
- } catch (NumberFormatException e) {}
- }
-
- NotificationCompat.Builder mBuilder =
- new NotificationCompat.Builder(context)
- .setDefaults(defaults)
- .setSmallIcon(context.getApplicationInfo().icon)
- .setWhen(System.currentTimeMillis())
- .setContentTitle(extras.getString("title"))
- .setTicker(extras.getString("title"))
- .setContentIntent(contentIntent)
- .setAutoCancel(true);
-
- String message = extras.getString("message");
- if (message != null) {
- mBuilder.setContentText(message);
- } else {
- mBuilder.setContentText("");
- }
-
- String msgcnt = extras.getString("msgcnt");
- if (msgcnt != null) {
- mBuilder.setNumber(Integer.parseInt(msgcnt));
- }
-
- int notId = 0;
-
- try {
- notId = Integer.parseInt(extras.getString("notId"));
- }
- catch(NumberFormatException e) {
- Log.e(TAG, "Number format exception - Error parsing Notification ID: " + e.getMessage());
- }
- catch(Exception e) {
- Log.e(TAG, "Number format exception - Error parsing Notification ID" + e.getMessage());
- }
-
- mNotificationManager.notify((String) appName, notId, mBuilder.build());
- }
-
- private static String getAppName(Context context)
- {
- CharSequence appName =
- context
- .getPackageManager()
- .getApplicationLabel(context.getApplicationInfo());
-
- return (String)appName;
- }
-
- @Override
- public void onError(Context context, String errorId) {
- Log.e(TAG, "onError - errorId: " + errorId);
- }
-
-}
diff --git a/src/android/com/plugin/gcm/PushPlugin.java b/src/android/com/plugin/gcm/PushPlugin.java
index 3e390856..8504df38 100644
--- a/src/android/com/plugin/gcm/PushPlugin.java
+++ b/src/android/com/plugin/gcm/PushPlugin.java
@@ -1,49 +1,63 @@
package com.plugin.gcm;
+import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
-import com.google.android.gcm.GCMRegistrar;
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaWebView;
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GooglePlayServicesUtil;
+import com.google.android.gms.gcm.GoogleCloudMessaging;
+import org.apache.cordova.*;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-import java.util.Iterator;
-
-/**
- * @author awysocki
- */
+import java.io.IOException;
public class PushPlugin extends CordovaPlugin {
public static final String TAG = "PushPlugin";
public static final String REGISTER = "register";
public static final String UNREGISTER = "unregister";
+ public static final String ARE_NOTIFICATIONS_ENABLED = "areNotificationsEnabled";
+ public static final String PROPERTY_REG_ID = "registration_id";
+ public static final String PROPERTY_APPVERSION = "app_version";
+ public static final String EXTRA_MESSAGE = "message";
public static final String EXIT = "exit";
+ private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private static CordovaWebView gWebView;
private static String gECB;
private static String gSenderID;
private static Bundle gCachedExtras = null;
- private static boolean gForeground = false;
+ private static boolean gForeground = false;
/**
* Gets the application context from cordova's main activity.
+ *
* @return the application context
*/
private Context getApplicationContext() {
return this.cordova.getActivity().getApplicationContext();
}
+ private Activity getApplicationActivity() {
+ return this.cordova.getActivity();
+ }
+
+ GoogleCloudMessaging gcm;
+ String regid;
+ Context context;
+
@Override
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) {
- boolean result = false;
+ boolean result;
Log.v(TAG, "execute: action=" + action);
@@ -62,24 +76,46 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackCo
Log.v(TAG, "execute: ECB=" + gECB + " senderID=" + gSenderID);
- GCMRegistrar.register(getApplicationContext(), gSenderID);
+ context = getApplicationContext();
+
+ regid = getRegistrationId(getApplicationContext());
+
+ if (regid.isEmpty()) {
+ new AsyncRegister().execute(callbackContext);
+ } else {
+ sendJavascript(new JSONObject().put("event", "registered").put("regid", regid));
+ callbackContext.success(regid);
+ }
result = true;
- callbackContext.success();
} catch (JSONException e) {
Log.e(TAG, "execute: Got JSON Exception " + e.getMessage());
result = false;
callbackContext.error(e.getMessage());
}
- if ( gCachedExtras != null) {
+ if (gCachedExtras != null) {
Log.v(TAG, "sending cached extras");
sendExtras(gCachedExtras);
gCachedExtras = null;
}
+ } else if (ARE_NOTIFICATIONS_ENABLED.equals(action)) {
+
+ Log.v(TAG, "ARE_NOTIFICATIONS_ENABLED");
+ final boolean registered = !getRegistrationId(getApplicationContext()).isEmpty();
+ Log.d(TAG, "areNotificationsEnabled? " + registered);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, registered));
+ result = true;
+
} else if (UNREGISTER.equals(action)) {
- GCMRegistrar.unregister(getApplicationContext());
+ GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(getApplicationContext());
+ try {
+ gcm.unregister();
+ removeRegistrationId(getApplicationContext());
+ } catch (IOException exception) {
+ Log.d(TAG, "IOException!");
+ }
Log.v(TAG, "UNREGISTER");
result = true;
@@ -93,9 +129,93 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackCo
return result;
}
- /*
- * Sends a json object to the client as parameter to a method which is defined in gECB.
+ /**
+ * Gets the current registration ID for application on GCM service.
+ *
+ * If result is empty, the app needs to register.
+ *
+ * @return registration ID, or empty string if there is no existing
+ * registration ID.
+ */
+ private String getRegistrationId(Context context) {
+ final SharedPreferences prefs = getGCMPreferences(context);
+ String registrationId = prefs.getString(PROPERTY_REG_ID, "");
+ if (registrationId.isEmpty()) {
+ Log.i(TAG, "Registration not found");
+ return "";
+ }
+ // Check if the app was updated; if so, it must clear the registration ID
+ // since the existing regID is not guaranteed to work with the new
+ // app version
+ String registeredVersion = prefs.getString(PROPERTY_APPVERSION, "");
+ String currentVersion = getVersion();
+ if (registeredVersion.equals(currentVersion)) {
+ Log.i(TAG, "Got registrationId from cache");
+ return registrationId;
+ }
+ return "";
+ }
+
+ private class AsyncRegister extends AsyncTask {
+ @Override
+ protected Void doInBackground(CallbackContext... callbackContext) {
+ try {
+ if (gcm == null) {
+ gcm = GoogleCloudMessaging.getInstance(getApplicationContext());
+ }
+ regid = gcm.register(gSenderID);
+ Log.v(TAG, "Device registered, registration ID=" + regid);
+ storeRegistrationId(getApplicationContext(), regid);
+ sendJavascript(new JSONObject().put("event", "registered").put("regid", regid));
+ callbackContext[0].success(regid);
+ } catch (Exception ex) {
+ Log.d(TAG, "Got Exception on registerInBackground", ex);
+ }
+ return null;
+ }
+ }
+
+ /**
+ * @return Application's {@code SharedPreferences}.
*/
+ private SharedPreferences getGCMPreferences(Context context) {
+ // This sample app persists the registration ID in shared preferences, but
+ // how you store the regID in your app is up to you.
+ //Log.d(TAG, "Activity: " + getApplicationActivity().toString());
+ //return context.getSharedPreferences(getApplicationActivity().toString(), Context.MODE_PRIVATE);
+ final String location = "PushPluginPreferences";
+ Log.d(TAG, "getGCMPreferences: " + location);
+ return context.getSharedPreferences(location, Context.MODE_PRIVATE);
+ }
+
+ /**
+ * Stores the registration ID and app versionCode in the application's
+ * {@code SharedPreferences}.
+ *
+ * @param context application's context.
+ * @param regId registration ID
+ */
+ private void storeRegistrationId(Context context, String regId) {
+ final SharedPreferences prefs = getGCMPreferences(context);
+ String appVersion = getVersion();
+ Log.i(TAG, "Saving registrationId on version " + appVersion);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(PROPERTY_REG_ID, regId);
+ editor.putString(PROPERTY_APPVERSION, appVersion);
+ editor.apply();
+ }
+
+ private void removeRegistrationId(Context context) {
+ final SharedPreferences prefs = getGCMPreferences(context);
+ Log.i(TAG, "Clearing registrationId");
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.remove(PROPERTY_REG_ID);
+ editor.apply();
+ }
+
+ /*
+ * Sends a json object to the client as parameter to a method which is defined in gECB.
+ */
public static void sendJavascript(JSONObject _json) {
String _d = "javascript:" + gECB + "(" + _json.toString() + ")";
Log.v(TAG, "sendJavascript: " + _d);
@@ -105,12 +225,21 @@ public static void sendJavascript(JSONObject _json) {
}
}
+ public String getVersion() {
+ try {
+ PackageManager packageManager = getApplicationActivity().getPackageManager();
+ return packageManager.getPackageInfo(getApplicationActivity().getPackageName(), 0).versionName;
+ } catch (NameNotFoundException exception) {
+ Log.d(TAG, "NameNotFoundException!");
+ return "";
+ }
+ }
+
/*
- * Sends the pushbundle extras to the client application.
- * If the client application isn't currently active, it is cached for later processing.
- */
- public static void sendExtras(Bundle extras)
- {
+ * Sends the pushbundle extras to the client application.
+ * If the client application isn't currently active, it is cached for later processing.
+ */
+ public static void sendExtras(Bundle extras) {
if (extras != null) {
if (gECB != null && gWebView != null) {
sendJavascript(convertBundleToJson(extras));
@@ -121,100 +250,95 @@ public static void sendExtras(Bundle extras)
}
}
- @Override
- public void initialize(CordovaInterface cordova, CordovaWebView webView) {
- super.initialize(cordova, webView);
- gForeground = true;
- }
+ @Override
+ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+ super.initialize(cordova, webView);
+ gForeground = true;
+ checkPlayServices();
+ }
@Override
- public void onPause(boolean multitasking) {
- super.onPause(multitasking);
- gForeground = false;
- final NotificationManager notificationManager = (NotificationManager) cordova.getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.cancelAll();
- }
-
- @Override
- public void onResume(boolean multitasking) {
- super.onResume(multitasking);
- gForeground = true;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- gForeground = false;
+ public void onPause(boolean multitasking) {
+ super.onPause(multitasking);
+ gForeground = false;
+ final NotificationManager notificationManager = (NotificationManager) cordova.getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.cancelAll();
+ }
+
+ @Override
+ public void onResume(boolean multitasking) {
+ super.onResume(multitasking);
+ gForeground = true;
+ checkPlayServices();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ gForeground = false;
gECB = null;
gWebView = null;
- }
-
- /*
- * serializes a bundle to JSON.
- */
- private static JSONObject convertBundleToJson(Bundle extras)
- {
- try
- {
+ }
+
+ private boolean checkPlayServices() {
+ int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
+ if (resultCode != ConnectionResult.SUCCESS) {
+ if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
+ GooglePlayServicesUtil.getErrorDialog(resultCode, this.cordova.getActivity(), PLAY_SERVICES_RESOLUTION_REQUEST).show();
+ } else {
+ Log.i(TAG, "This device does not support Play Services.");
+ // finish();
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /*
+ * serializes a bundle to JSON.
+ */
+ private static JSONObject convertBundleToJson(Bundle extras) {
+ try {
JSONObject json;
json = new JSONObject().put("event", "message");
JSONObject jsondata = new JSONObject();
- Iterator it = extras.keySet().iterator();
- while (it.hasNext())
- {
- String key = it.next();
+ for (String key : extras.keySet()) {
Object value = extras.get(key);
// System data from Android
- if (key.equals("from") || key.equals("collapse_key"))
- {
+ if (key.equals("from") || key.equals("collapse_key")) {
json.put(key, value);
- }
- else if (key.equals("foreground"))
- {
+ } else if (key.equals("foreground")) {
json.put(key, extras.getBoolean("foreground"));
- }
- else if (key.equals("coldstart"))
- {
+ } else if (key.equals("coldstart")) {
json.put(key, extras.getBoolean("coldstart"));
- }
- else
- {
+ } else {
// Maintain backwards compatibility
- if (key.equals("message") || key.equals("msgcnt") || key.equals("soundname"))
- {
+ if (key.equals("message") || key.equals("msgcnt") || key.equals("soundname")) {
json.put(key, value);
}
- if ( value instanceof String ) {
- // Try to figure out if the value is another JSON object
+ if (value instanceof String) {
+ // Try to figure out if the value is another JSON object
- String strValue = (String)value;
+ String strValue = (String) value;
if (strValue.startsWith("{")) {
try {
JSONObject json2 = new JSONObject(strValue);
jsondata.put(key, json2);
- }
- catch (Exception e) {
+ } catch (Exception e) {
jsondata.put(key, value);
}
// Try to figure out if the value is another JSON array
- }
- else if (strValue.startsWith("["))
- {
- try
- {
+ } else if (strValue.startsWith("[")) {
+ try {
JSONArray json2 = new JSONArray(strValue);
jsondata.put(key, json2);
- }
- catch (Exception e)
- {
+ } catch (Exception e) {
jsondata.put(key, value);
}
- }
- else
- {
+ } else {
jsondata.put(key, value);
}
}
@@ -225,21 +349,17 @@ else if (strValue.startsWith("["))
Log.v(TAG, "extrasToJSON: " + json.toString());
return json;
- }
- catch( JSONException e)
- {
+ } catch (JSONException e) {
Log.e(TAG, "extrasToJSON: JSON exception");
}
return null;
- }
+ }
- public static boolean isInForeground()
- {
- return gForeground;
- }
+ public static boolean isInForeground() {
+ return gForeground;
+ }
- public static boolean isActive()
- {
- return gWebView != null;
- }
+ public static boolean isActive() {
+ return gWebView != null;
+ }
}
diff --git a/src/android/libs/gcm.jar b/src/android/libs/gcm.jar
deleted file mode 100644
index ac109a83..00000000
Binary files a/src/android/libs/gcm.jar and /dev/null differ
diff --git a/src/ios/AppDelegate+notification.m b/src/ios/AppDelegate+notification.m
index aa563a34..2da63227 100644
--- a/src/ios/AppDelegate+notification.m
+++ b/src/ios/AppDelegate+notification.m
@@ -16,103 +16,125 @@ @implementation AppDelegate (notification)
- (id) getCommandInstance:(NSString*)className
{
- return [self.viewController getCommandInstance:className];
+ return [self.viewController getCommandInstance:className];
}
// its dangerous to override a method from within a category.
// Instead we will use method swizzling. we set this up in the load call.
+ (void)load
{
- Method original, swizzled;
-
- original = class_getInstanceMethod(self, @selector(init));
- swizzled = class_getInstanceMethod(self, @selector(swizzled_init));
- method_exchangeImplementations(original, swizzled);
+ Method original, swizzled;
+
+ original = class_getInstanceMethod(self, @selector(init));
+ swizzled = class_getInstanceMethod(self, @selector(swizzled_init));
+ method_exchangeImplementations(original, swizzled);
}
- (AppDelegate *)swizzled_init
{
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(createNotificationChecker:)
- name:@"UIApplicationDidFinishLaunchingNotification" object:nil];
-
- // This actually calls the original init method over in AppDelegate. Equivilent to calling super
- // on an overrided method, this is not recursive, although it appears that way. neat huh?
- return [self swizzled_init];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(createNotificationChecker:)
+ name:@"UIApplicationDidFinishLaunchingNotification" object:nil];
+
+ // This actually calls the original init method over in AppDelegate. Equivilent to calling super
+ // on an overrided method, this is not recursive, although it appears that way. neat huh?
+ return [self swizzled_init];
}
// This code will be called immediately after application:didFinishLaunchingWithOptions:. We need
// to process notifications in cold-start situations
- (void)createNotificationChecker:(NSNotification *)notification
{
- if (notification)
- {
- NSDictionary *launchOptions = [notification userInfo];
- if (launchOptions)
- self.launchNotification = [launchOptions objectForKey: @"UIApplicationLaunchOptionsRemoteNotificationKey"];
- }
+ if (notification)
+ {
+ NSDictionary *launchOptions = [notification userInfo];
+ if (launchOptions)
+ self.launchNotification = [launchOptions objectForKey: @"UIApplicationLaunchOptionsRemoteNotificationKey"];
+ }
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
- PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
- [pushHandler didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
+ PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
+ [pushHandler didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
- PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
- [pushHandler didFailToRegisterForRemoteNotificationsWithError:error];
+ PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
+ [pushHandler didFailToRegisterForRemoteNotificationsWithError:error];
}
+// this method is invoked when:
+// - a regular notification is tapped
+// - an interactive notification is tapped, but not one of its buttons
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
- NSLog(@"didReceiveNotification");
-
- // Get application state for iOS4.x+ devices, otherwise assume active
- UIApplicationState appState = UIApplicationStateActive;
- if ([application respondsToSelector:@selector(applicationState)]) {
- appState = application.applicationState;
- }
-
- if (appState == UIApplicationStateActive) {
- PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
- pushHandler.notificationMessage = userInfo;
- pushHandler.isInline = YES;
- [pushHandler notificationReceived];
- } else {
- //save it for later
- self.launchNotification = userInfo;
- }
+ NSLog(@"didReceiveNotification");
+
+ if (application.applicationState == UIApplicationStateActive) {
+ PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
+ pushHandler.notificationMessage = userInfo;
+ pushHandler.isInline = YES;
+ [pushHandler notificationReceived];
+ } else {
+ //save it for later
+ self.launchNotification = userInfo;
+ }
+}
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
+// this method is invoked when:
+// - one of the buttons of an interactive notification is tapped
+// see https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW1
+- (void)application:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier forRemoteNotification: (NSDictionary *) notification completionHandler: (void (^)()) completionHandler {
+
+ // the notification already contains the category, but the client also needs the identifier (action button)
+ NSMutableDictionary *mutableNotification = [notification mutableCopy];
+
+ [mutableNotification setObject:identifier forKey:@"identifier"];
+ if (application.applicationState == UIApplicationStateActive) {
+ PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
+ pushHandler.notificationMessage = mutableNotification;
+ pushHandler.isInline = YES;
+ [pushHandler notificationReceived];
+ } else {
+ PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
+ pushHandler.notificationMessage = mutableNotification;
+ [pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO];
+ }
+ completionHandler();
}
+#endif
+
- (void)applicationDidBecomeActive:(UIApplication *)application {
+
+ NSLog(@"active");
+
+ //zero badge
+ application.applicationIconBadgeNumber = 0;
+
+ if (self.launchNotification) {
+ PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
- NSLog(@"active");
-
- //zero badge
- application.applicationIconBadgeNumber = 0;
-
- if (self.launchNotification) {
- PushPlugin *pushHandler = [self getCommandInstance:@"PushPlugin"];
-
- pushHandler.notificationMessage = self.launchNotification;
- self.launchNotification = nil;
- [pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO];
- }
+ pushHandler.notificationMessage = self.launchNotification;
+ self.launchNotification = nil;
+ [pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO];
+ }
}
// The accessors use an Associative Reference since you can't define a iVar in a category
// http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocAssociativeReferences.html
- (NSMutableArray *)launchNotification
{
- return objc_getAssociatedObject(self, &launchNotificationKey);
+ return objc_getAssociatedObject(self, &launchNotificationKey);
}
- (void)setLaunchNotification:(NSDictionary *)aDictionary
{
- objc_setAssociatedObject(self, &launchNotificationKey, aDictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ objc_setAssociatedObject(self, &launchNotificationKey, aDictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)dealloc
{
- self.launchNotification = nil; // clear the association and release the object
+ self.launchNotification = nil; // clear the association and release the object
}
@end
diff --git a/src/ios/PushPlugin.h b/src/ios/PushPlugin.h
index 7e7ba4bc..b1ec8ffa 100644
--- a/src/ios/PushPlugin.h
+++ b/src/ios/PushPlugin.h
@@ -33,7 +33,6 @@
BOOL isInline;
NSString *notificationCallbackId;
NSString *callback;
-
BOOL ready;
}
@@ -45,6 +44,9 @@
@property BOOL isInline;
- (void)register:(CDVInvokedUrlCommand*)command;
+- (void)registerUserNotificationSettings:(CDVInvokedUrlCommand*)command;
+
+- (void)areNotificationsEnabled:(CDVInvokedUrlCommand*)command;
- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m
index 7686ae9d..a3a3440e 100644
--- a/src/ios/PushPlugin.m
+++ b/src/ios/PushPlugin.m
@@ -37,244 +37,390 @@ @implementation PushPlugin
- (void)unregister:(CDVInvokedUrlCommand*)command;
{
- self.callbackId = command.callbackId;
+ self.callbackId = command.callbackId;
+
+ [[UIApplication sharedApplication] unregisterForRemoteNotifications];
+ [self successWithMessage:@"unregistered"];
+}
- [[UIApplication sharedApplication] unregisterForRemoteNotifications];
- [self successWithMessage:@"unregistered"];
+- (void)areNotificationsEnabled:(CDVInvokedUrlCommand*)command;
+{
+ self.callbackId = command.callbackId;
+ BOOL registered;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
+ if ([[UIApplication sharedApplication] respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
+ registered = [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
+ } else {
+ UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
+ registered = types != UIRemoteNotificationTypeNone;
+ }
+#else
+ UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
+ registered = types != UIRemoteNotificationTypeNone;
+#endif
+ CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:registered];
+ [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId];
}
-- (void)register:(CDVInvokedUrlCommand*)command;
+- (void)registerUserNotificationSettings:(CDVInvokedUrlCommand*)command;
{
- self.callbackId = command.callbackId;
+ self.callbackId = command.callbackId;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
+ if (![[UIApplication sharedApplication]respondsToSelector:@selector(registerUserNotificationSettings:)]) {
+ [self successWithMessage:[NSString stringWithFormat:@"%@", @"user notifications not supported for this ios version."]];
+ return;
+ }
+
+ NSDictionary *options = [command.arguments objectAtIndex:0];
+ NSArray *categories = [options objectForKey:@"categories"];
+ if (categories == nil) {
+ [self failWithMessage:@"No categories specified" withError:nil];
+ return;
+ }
+ NSMutableArray *nsCategories = [[NSMutableArray alloc] initWithCapacity:[categories count]];
+
+ for (NSDictionary *category in categories) {
+ // ** 1. create the actions for this category
+ NSMutableArray *nsActionsForDefaultContext = [[NSMutableArray alloc] initWithCapacity:4];
+ NSArray *actionsForDefaultContext = [category objectForKey:@"actionsForDefaultContext"];
+ if (actionsForDefaultContext == nil) {
+ [self failWithMessage:@"Category doesn't contain actionsForDefaultContext" withError:nil];
+ return;
+ }
+ if (![self createNotificationAction:category actions:actionsForDefaultContext nsActions:nsActionsForDefaultContext]) {
+ return;
+ }
- NSMutableDictionary* options = [command.arguments objectAtIndex:0];
+ NSMutableArray *nsActionsForMinimalContext = [[NSMutableArray alloc] initWithCapacity:2];
+ NSArray *actionsForMinimalContext = [category objectForKey:@"actionsForMinimalContext"];
+ if (actionsForMinimalContext == nil) {
+ [self failWithMessage:@"Category doesn't contain actionsForMinimalContext" withError:nil];
+ return;
+ }
+ if (![self createNotificationAction:category actions:actionsForMinimalContext nsActions:nsActionsForMinimalContext]) {
+ return;
+ }
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- UIUserNotificationType UserNotificationTypes = UIUserNotificationTypeNone;
+ // ** 2. create the category
+ UIMutableUserNotificationCategory *nsCategory = [[UIMutableUserNotificationCategory alloc] init];
+ // Identifier to include in your push payload and local notification
+ NSString *identifier = [category objectForKey:@"identifier"];
+ if (identifier == nil) {
+ [self failWithMessage:@"Category doesn't contain identifier" withError:nil];
+ return;
+ }
+ nsCategory.identifier = identifier;
+ // Add the actions to the category and set the action context
+ [nsCategory setActions:nsActionsForDefaultContext forContext:UIUserNotificationActionContextDefault];
+ // Set the actions to present in a minimal context
+ [nsCategory setActions:nsActionsForMinimalContext forContext:UIUserNotificationActionContextMinimal];
+ [nsCategories addObject:nsCategory];
+ }
+
+ // ** 3. Determine the notification types
+ NSArray *types = [options objectForKey:@"types"];
+ if (types == nil) {
+ [self failWithMessage:@"No types specified" withError:nil];
+ return;
+ }
+ UIUserNotificationType nsTypes = UIUserNotificationTypeNone;
+ for (NSString *type in types) {
+ if ([type isEqualToString:@"badge"]) {
+ nsTypes |= UIUserNotificationTypeBadge;
+ } else if ([type isEqualToString:@"alert"]) {
+ nsTypes |= UIUserNotificationTypeAlert;
+ } else if ([type isEqualToString:@"sound"]) {
+ nsTypes |= UIUserNotificationTypeSound;
+ } else {
+ [self failWithMessage:[NSString stringWithFormat:@"Unsupported type: %@, use one of badge, alert, sound", type] withError:nil];
+ }
+ }
+
+ // ** 4. Register the notification categories
+ NSSet *nsCategorySet = [NSSet setWithArray:nsCategories];
+ UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:nsTypes categories:nsCategorySet];
+ [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
#endif
- UIRemoteNotificationType notificationTypes = UIRemoteNotificationTypeNone;
+ [self successWithMessage:[NSString stringWithFormat:@"%@", @"user notifications registered"]];
+}
- id badgeArg = [options objectForKey:@"badge"];
- id soundArg = [options objectForKey:@"sound"];
- id alertArg = [options objectForKey:@"alert"];
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
+- (BOOL)createNotificationAction:(NSDictionary *)category
+ actions:(NSArray *) actions
+ nsActions:(NSMutableArray *)nsActions
+{
+ for (NSDictionary *action in actions) {
+ UIMutableUserNotificationAction *nsAction = [[UIMutableUserNotificationAction alloc] init];
+ // Define an ID string to be passed back to your app when you handle the action
+ NSString *identifier = [action objectForKey:@"identifier"];
+ if (identifier == nil) {
+ [self failWithMessage:@"Action doesn't contain identifier" withError:nil];
+ return NO;
+ }
+ nsAction.identifier = identifier;
+ // Localized text displayed in the action button
+ NSString *title = [action objectForKey:@"title"];
+ if (title == nil) {
+ [self failWithMessage:@"Action doesn't contain title" withError:nil];
+ return NO;
+ }
+ nsAction.title = title;
+ // If you need to show UI, choose foreground (background gives your app a few seconds to run)
+ BOOL isForeground = [@"foreground" isEqualToString:[action objectForKey:@"activationMode"]];
+ nsAction.activationMode = isForeground ? UIUserNotificationActivationModeForeground : UIUserNotificationActivationModeBackground;
+ // Destructive actions display in red
+ BOOL isDestructive = [[action objectForKey:@"destructive"] isEqual:[NSNumber numberWithBool:YES]];
+ nsAction.destructive = isDestructive;
+ // Set whether the action requires the user to authenticate
+ BOOL isAuthRequired = [[action objectForKey:@"authenticationRequired"] isEqual:[NSNumber numberWithBool:YES]];
+ nsAction.authenticationRequired = isAuthRequired;
+ [nsActions addObject:nsAction];
+ }
+ return YES;
+}
+#endif
- if ([badgeArg isKindOfClass:[NSString class]])
- {
- if ([badgeArg isEqualToString:@"true"]) {
- notificationTypes |= UIRemoteNotificationTypeBadge;
+- (void)register:(CDVInvokedUrlCommand*)command;
+{
+ self.callbackId = command.callbackId;
+
+ NSMutableDictionary* options = [command.arguments objectAtIndex:0];
+
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- UserNotificationTypes |= UIUserNotificationTypeBadge;
+ UIUserNotificationType UserNotificationTypes = UIUserNotificationTypeNone;
#endif
- }
- }
- else if ([badgeArg boolValue]) {
- notificationTypes |= UIRemoteNotificationTypeBadge;
+ UIRemoteNotificationType notificationTypes = UIRemoteNotificationTypeNone;
+
+ id badgeArg = [options objectForKey:@"badge"];
+ id soundArg = [options objectForKey:@"sound"];
+ id alertArg = [options objectForKey:@"alert"];
+
+ if ([badgeArg isKindOfClass:[NSString class]])
+ {
+ if ([badgeArg isEqualToString:@"true"]) {
+ notificationTypes |= UIRemoteNotificationTypeBadge;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- UserNotificationTypes |= UIUserNotificationTypeBadge;
+ UserNotificationTypes |= UIUserNotificationTypeBadge;
#endif
}
-
- if ([soundArg isKindOfClass:[NSString class]])
- {
- if ([soundArg isEqualToString:@"true"]) {
- notificationTypes |= UIRemoteNotificationTypeSound;
+ }
+ else if ([badgeArg boolValue]) {
+ notificationTypes |= UIRemoteNotificationTypeBadge;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- UserNotificationTypes |= UIUserNotificationTypeSound;
+ UserNotificationTypes |= UIUserNotificationTypeBadge;
#endif
- }
- }
- else if ([soundArg boolValue]) {
- notificationTypes |= UIRemoteNotificationTypeSound;
+ }
+
+ if ([soundArg isKindOfClass:[NSString class]])
+ {
+ if ([soundArg isEqualToString:@"true"]) {
+ notificationTypes |= UIRemoteNotificationTypeSound;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- UserNotificationTypes |= UIUserNotificationTypeSound;
+ UserNotificationTypes |= UIUserNotificationTypeSound;
#endif
}
-
- if ([alertArg isKindOfClass:[NSString class]])
- {
- if ([alertArg isEqualToString:@"true"]) {
- notificationTypes |= UIRemoteNotificationTypeAlert;
+ }
+ else if ([soundArg boolValue]) {
+ notificationTypes |= UIRemoteNotificationTypeSound;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- UserNotificationTypes |= UIUserNotificationTypeAlert;
+ UserNotificationTypes |= UIUserNotificationTypeSound;
#endif
- }
- }
- else if ([alertArg boolValue]) {
- notificationTypes |= UIRemoteNotificationTypeAlert;
+ }
+
+ if ([alertArg isKindOfClass:[NSString class]])
+ {
+ if ([alertArg isEqualToString:@"true"]) {
+ notificationTypes |= UIRemoteNotificationTypeAlert;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- UserNotificationTypes |= UIUserNotificationTypeAlert;
+ UserNotificationTypes |= UIUserNotificationTypeAlert;
#endif
}
-
- notificationTypes |= UIRemoteNotificationTypeNewsstandContentAvailability;
+ }
+ else if ([alertArg boolValue]) {
+ notificationTypes |= UIRemoteNotificationTypeAlert;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- UserNotificationTypes |= UIUserNotificationActivationModeBackground;
+ UserNotificationTypes |= UIUserNotificationTypeAlert;
#endif
-
- self.callback = [options objectForKey:@"ecb"];
-
- if (notificationTypes == UIRemoteNotificationTypeNone)
- NSLog(@"PushPlugin.register: Push notification type is set to none");
-
- isInline = NO;
-
+ }
+
+ notificationTypes |= UIRemoteNotificationTypeNewsstandContentAvailability;
+//#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
+// UserNotificationTypes |= UIUserNotificationActivationModeBackground;
+//#endif
+
+ self.callback = [options objectForKey:@"ecb"];
+
+ if (notificationTypes == UIRemoteNotificationTypeNone)
+ NSLog(@"PushPlugin.register: Push notification type is set to none");
+
+ isInline = NO;
+
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- if ([[UIApplication sharedApplication]respondsToSelector:@selector(registerUserNotificationSettings:)]) {
- UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UserNotificationTypes categories:nil];
- [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
- [[UIApplication sharedApplication] registerForRemoteNotifications];
- } else {
- [[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationTypes];
- }
+ if ([[UIApplication sharedApplication]respondsToSelector:@selector(registerUserNotificationSettings:)]) {
+ UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UserNotificationTypes categories:nil];
+ [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
+ [[UIApplication sharedApplication] registerForRemoteNotifications];
+ } else {
+ [[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationTypes];
+ }
#else
- [[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationTypes];
+ [[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationTypes];
#endif
-
- if (notificationMessage) // if there is a pending startup notification
- [self notificationReceived]; // go ahead and process it
+
+ if (notificationMessage) // if there is a pending startup notification
+ [self notificationReceived]; // go ahead and process it
}
/*
-- (void)isEnabled:(NSMutableArray *)arguments withDict:(NSMutableDictionary *)options {
- UIRemoteNotificationType type = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
- NSString *jsStatement = [NSString stringWithFormat:@"navigator.PushPlugin.isEnabled = %d;", type != UIRemoteNotificationTypeNone];
- NSLog(@"JSStatement %@",jsStatement);
-}
-*/
+ - (void)isEnabled:(NSMutableArray *)arguments withDict:(NSMutableDictionary *)options {
+ UIRemoteNotificationType type = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
+ NSString *jsStatement = [NSString stringWithFormat:@"navigator.PushPlugin.isEnabled = %d;", type != UIRemoteNotificationTypeNone];
+ NSLog(@"JSStatement %@",jsStatement);
+ }
+ */
- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
-
- NSMutableDictionary *results = [NSMutableDictionary dictionary];
- NSString *token = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""]
- stringByReplacingOccurrencesOfString:@">" withString:@""]
- stringByReplacingOccurrencesOfString: @" " withString: @""];
- [results setValue:token forKey:@"deviceToken"];
-
- #if !TARGET_IPHONE_SIMULATOR
- // Get Bundle Info for Remote Registration (handy if you have more than one app)
- [results setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"] forKey:@"appName"];
- [results setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] forKey:@"appVersion"];
-
- // Check what Notifications the user has turned on. We registered for all three, but they may have manually disabled some or all of them.
- NSUInteger rntypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
-
- // Set the defaults to disabled unless we find otherwise...
- NSString *pushBadge = @"disabled";
- NSString *pushAlert = @"disabled";
- NSString *pushSound = @"disabled";
-
- // Check what Registered Types are turned on. This is a bit tricky since if two are enabled, and one is off, it will return a number 2... not telling you which
- // one is actually disabled. So we are literally checking to see if rnTypes matches what is turned on, instead of by number. The "tricky" part is that the
- // single notification types will only match if they are the ONLY one enabled. Likewise, when we are checking for a pair of notifications, it will only be
- // true if those two notifications are on. This is why the code is written this way
- if(rntypes & UIRemoteNotificationTypeBadge){
- pushBadge = @"enabled";
- }
- if(rntypes & UIRemoteNotificationTypeAlert) {
- pushAlert = @"enabled";
- }
- if(rntypes & UIRemoteNotificationTypeSound) {
- pushSound = @"enabled";
- }
-
- [results setValue:pushBadge forKey:@"pushBadge"];
- [results setValue:pushAlert forKey:@"pushAlert"];
- [results setValue:pushSound forKey:@"pushSound"];
-
- // Get the users Device Model, Display Name, Token & Version Number
- UIDevice *dev = [UIDevice currentDevice];
- [results setValue:dev.name forKey:@"deviceName"];
- [results setValue:dev.model forKey:@"deviceModel"];
- [results setValue:dev.systemVersion forKey:@"deviceSystemVersion"];
-
- [self successWithMessage:[NSString stringWithFormat:@"%@", token]];
- #endif
+
+ NSMutableDictionary *results = [NSMutableDictionary dictionary];
+ NSString *token = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""]
+ stringByReplacingOccurrencesOfString:@">" withString:@""]
+ stringByReplacingOccurrencesOfString: @" " withString: @""];
+ [results setValue:token forKey:@"deviceToken"];
+
+#if !TARGET_IPHONE_SIMULATOR
+ // Get Bundle Info for Remote Registration (handy if you have more than one app)
+ [results setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"] forKey:@"appName"];
+ [results setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] forKey:@"appVersion"];
+
+ // Check what Notifications the user has turned on. We registered for all three, but they may have manually disabled some or all of them.
+ NSUInteger rntypes;
+ #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
+ if([UIUserNotificationSettings class]){
+ rntypes = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
+ } else {
+ rntypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
+ }
+ #else
+ rntypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
+ #endif
+
+ // Set the defaults to disabled unless we find otherwise...
+ NSString *pushBadge = @"disabled";
+ NSString *pushAlert = @"disabled";
+ NSString *pushSound = @"disabled";
+
+ // Check what Registered Types are turned on. This is a bit tricky since if two are enabled, and one is off, it will return a number 2... not telling you which
+ // one is actually disabled. So we are literally checking to see if rnTypes matches what is turned on, instead of by number. The "tricky" part is that the
+ // single notification types will only match if they are the ONLY one enabled. Likewise, when we are checking for a pair of notifications, it will only be
+ // true if those two notifications are on. This is why the code is written this way
+ if(rntypes & UIRemoteNotificationTypeBadge){
+ pushBadge = @"enabled";
+ }
+ if(rntypes & UIRemoteNotificationTypeAlert) {
+ pushAlert = @"enabled";
+ }
+ if(rntypes & UIRemoteNotificationTypeSound) {
+ pushSound = @"enabled";
+ }
+
+ [results setValue:pushBadge forKey:@"pushBadge"];
+ [results setValue:pushAlert forKey:@"pushAlert"];
+ [results setValue:pushSound forKey:@"pushSound"];
+
+ // Get the users Device Model, Display Name, Token & Version Number
+ UIDevice *dev = [UIDevice currentDevice];
+ [results setValue:dev.name forKey:@"deviceName"];
+ [results setValue:dev.model forKey:@"deviceModel"];
+ [results setValue:dev.systemVersion forKey:@"deviceSystemVersion"];
+
+ [self successWithMessage:[NSString stringWithFormat:@"%@", token]];
+#endif
}
- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
- [self failWithMessage:@"" withError:error];
+ [self failWithMessage:@"" withError:error];
}
- (void)notificationReceived {
- NSLog(@"Notification received");
-
- if (notificationMessage && self.callback)
+ NSLog(@"Notification received");
+
+ if (notificationMessage && self.callback)
+ {
+ NSMutableString *jsonStr = [NSMutableString stringWithString:@"{"];
+
+ [self parseDictionary:notificationMessage intoJSON:jsonStr];
+
+ if (isInline)
{
- NSMutableString *jsonStr = [NSMutableString stringWithString:@"{"];
-
- [self parseDictionary:notificationMessage intoJSON:jsonStr];
-
- if (isInline)
- {
- [jsonStr appendFormat:@"foreground:\"%d\"", 1];
- isInline = NO;
- }
- else
- [jsonStr appendFormat:@"foreground:\"%d\"", 0];
-
- [jsonStr appendString:@"}"];
-
- NSLog(@"Msg: %@", jsonStr);
-
- NSString * jsCallBack = [NSString stringWithFormat:@"%@(%@);", self.callback, jsonStr];
- [self.webView stringByEvaluatingJavaScriptFromString:jsCallBack];
-
- self.notificationMessage = nil;
+ [jsonStr appendFormat:@"foreground:\"%d\"", 1];
+ isInline = NO;
}
+ else
+ [jsonStr appendFormat:@"foreground:\"%d\"", 0];
+
+ [jsonStr appendString:@"}"];
+
+ NSLog(@"Msg: %@", jsonStr);
+
+ NSString * jsCallBack = [NSString stringWithFormat:@"%@(%@);", self.callback, jsonStr];
+ [self.webView stringByEvaluatingJavaScriptFromString:jsCallBack];
+
+ self.notificationMessage = nil;
+ }
}
// reentrant method to drill down and surface all sub-dictionaries' key/value pairs into the top level json
-(void)parseDictionary:(NSDictionary *)inDictionary intoJSON:(NSMutableString *)jsonString
{
- NSArray *keys = [inDictionary allKeys];
- NSString *key;
-
- for (key in keys)
- {
- id thisObject = [inDictionary objectForKey:key];
-
- if ([thisObject isKindOfClass:[NSDictionary class]])
- [self parseDictionary:thisObject intoJSON:jsonString];
- else if ([thisObject isKindOfClass:[NSString class]])
- [jsonString appendFormat:@"\"%@\":\"%@\",",
- key,
- [[[[inDictionary objectForKey:key]
- stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]
- stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]
- stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]];
- else {
- [jsonString appendFormat:@"\"%@\":\"%@\",", key, [inDictionary objectForKey:key]];
- }
+ NSArray *keys = [inDictionary allKeys];
+ NSString *key;
+
+ for (key in keys)
+ {
+ id thisObject = [inDictionary objectForKey:key];
+
+ if ([thisObject isKindOfClass:[NSDictionary class]])
+ [self parseDictionary:thisObject intoJSON:jsonString];
+ else if ([thisObject isKindOfClass:[NSString class]])
+ [jsonString appendFormat:@"\"%@\":\"%@\",",
+ key,
+ [[[[inDictionary objectForKey:key]
+ stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]
+ stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]
+ stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]];
+ else {
+ [jsonString appendFormat:@"\"%@\":\"%@\",", key, [inDictionary objectForKey:key]];
}
+ }
}
- (void)setApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command {
-
- self.callbackId = command.callbackId;
-
- NSMutableDictionary* options = [command.arguments objectAtIndex:0];
- int badge = [[options objectForKey:@"badge"] intValue] ?: 0;
-
- [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge];
-
- [self successWithMessage:[NSString stringWithFormat:@"app badge count set to %d", badge]];
+
+ self.callbackId = command.callbackId;
+
+ NSMutableDictionary* options = [command.arguments objectAtIndex:0];
+ int badge = [[options objectForKey:@"badge"] intValue] ?: 0;
+
+ [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge];
+
+ [self successWithMessage:[NSString stringWithFormat:@"app badge count set to %d", badge]];
}
-(void)successWithMessage:(NSString *)message
{
- if (self.callbackId != nil)
- {
- CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message];
- [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId];
- }
+ if (self.callbackId != nil)
+ {
+ CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message];
+ [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId];
+ }
}
-(void)failWithMessage:(NSString *)message withError:(NSError *)error
{
- NSString *errorMessage = (error) ? [NSString stringWithFormat:@"%@ - %@", message, [error localizedDescription]] : message;
- CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorMessage];
-
- [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId];
+ NSString *errorMessage = (error) ? [NSString stringWithFormat:@"%@ - %@", message, [error localizedDescription]] : message;
+ CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorMessage];
+
+ [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId];
}
@end
diff --git a/src/wp8/PushPlugin.cs b/src/wp8/PushPlugin.cs
index 53d318f9..a3688387 100644
--- a/src/wp8/PushPlugin.cs
+++ b/src/wp8/PushPlugin.cs
@@ -29,7 +29,7 @@ public void register(string options)
if (pushChannel == null)
{
pushChannel = new HttpNotificationChannel(this.pushOptions.ChannelName);
-
+ SubscribePushChannelEvents(pushChannel);
try
{
pushChannel.Open();
@@ -43,15 +43,28 @@ public void register(string options)
pushChannel.BindToShellToast();
pushChannel.BindToShellTile();
}
-
- SubscribePushChannelEvents(pushChannel);
- var result = new RegisterResult
+ else
{
- ChannelName = this.pushOptions.ChannelName,
- Uri = pushChannel.ChannelUri == null ? string.Empty : pushChannel.ChannelUri.ToString()
- };
+ SubscribePushChannelEvents(pushChannel);
+ }
- this.DispatchCommandResult(new PluginResult(PluginResult.Status.OK, result));
+ if (pushChannel.ChannelUri == null)
+ {
+ // Wait for the channel to become ready.
+ // Need to respond with OK instead of NO_RESULT because of https://issues.apache.org/jira/browse/CB-8580
+ PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
+ pluginResult.KeepCallback = true;
+ this.DispatchCommandResult(pluginResult, this.CurrentCommandCallbackId);
+ }
+ else
+ {
+ var result = new RegisterResult
+ {
+ ChannelName = this.pushOptions.ChannelName,
+ Uri = pushChannel.ChannelUri.ToString()
+ };
+ this.DispatchCommandResult(new PluginResult(PluginResult.Status.OK, result));
+ }
}
public void unregister(string options)
@@ -77,6 +90,18 @@ public void unregister(string options)
}
}
+ public void areNotificationsEnabled(string options)
+ {
+ Options isRegisteredOptions;
+ if (!TryDeserializeOptions(options, out isRegisteredOptions))
+ {
+ this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+ return;
+ }
+ var pushChannel = HttpNotificationChannel.Find(isRegisteredOptions.ChannelName);
+ this.DispatchCommandResult(new PluginResult(PluginResult.Status.OK, pushChannel != null));
+ }
+
public void showToastNotification(string options)
{
ShellToast toast;
@@ -97,6 +122,10 @@ void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArg
ChannelName = this.pushOptions.ChannelName,
Uri = e.ChannelUri.ToString()
};
+ if (this.CurrentCommandCallbackId != null)
+ {
+ this.DispatchCommandResult(new PluginResult(PluginResult.Status.OK, result));
+ }
this.ExecuteCallback(this.pushOptions.UriChangedCallback, JsonConvert.SerializeObject(result));
}
diff --git a/www/PushNotification.js b/www/PushNotification.js
index 6127cf56..15e247ce 100644
--- a/www/PushNotification.js
+++ b/www/PushNotification.js
@@ -19,6 +19,34 @@ PushNotification.prototype.register = function(successCallback, errorCallback, o
cordova.exec(successCallback, errorCallback, "PushPlugin", "register", [options]);
};
+PushNotification.prototype.UserNotificationTypes = {
+ Badge : "badge",
+ Alert : "alert",
+ Sound : "sound"
+};
+
+PushNotification.prototype.UserNotificationActivationMode = {
+ Foreground : "foreground",
+ Background : "background"
+};
+
+PushNotification.prototype.registerUserNotificationSettings = function(successCallback, errorCallback, options) {
+ if (errorCallback == null) { errorCallback = function() {}}
+
+ if (typeof errorCallback != "function") {
+ console.log("PushNotification.registerUserNotificationSettings failure: failure parameter not a function");
+ return
+ }
+
+ if (typeof successCallback != "function") {
+ console.log("PushNotification.registerUserNotificationSettings failure: success callback parameter must be a function");
+ return
+ }
+
+ cordova.exec(successCallback, errorCallback, "PushPlugin", "registerUserNotificationSettings", [options]);
+};
+
+
// Call this to unregister for push notifications
PushNotification.prototype.unregister = function(successCallback, errorCallback, options) {
if (errorCallback == null) { errorCallback = function() {}}
@@ -36,17 +64,35 @@ PushNotification.prototype.unregister = function(successCallback, errorCallback,
cordova.exec(successCallback, errorCallback, "PushPlugin", "unregister", [options]);
};
- // Call this if you want to show toast notification on WP8
- PushNotification.prototype.showToastNotification = function (successCallback, errorCallback, options) {
- if (errorCallback == null) { errorCallback = function () { } }
+// Check to see if we've already registered
+PushNotification.prototype.areNotificationsEnabled = function(successCallback, errorCallback, options) {
+ if (errorCallback == null) { errorCallback = function() {}}
+
+ if (typeof errorCallback != "function") {
+ console.log("PushNotification.areNotificationsEnabled failure: failure parameter not a function");
+ return
+ }
+
+ if (typeof successCallback != "function") {
+ console.log("PushNotification.areNotificationsEnabled failure: success callback parameter must be a function");
+ return
+ }
+
+ cordova.exec(successCallback, errorCallback, "PushPlugin", "areNotificationsEnabled", [options]);
+};
- if (typeof errorCallback != "function") {
- console.log("PushNotification.register failure: failure parameter not a function");
- return
- }
+// Call this if you want to show toast notification on WP8
+PushNotification.prototype.showToastNotification = function (successCallback, errorCallback, options) {
+ if (errorCallback == null) { errorCallback = function () { } }
- cordova.exec(successCallback, errorCallback, "PushPlugin", "showToastNotification", [options]);
+ if (typeof errorCallback != "function") {
+ console.log("PushNotification.register failure: failure parameter not a function");
+ return
}
+
+ cordova.exec(successCallback, errorCallback, "PushPlugin", "showToastNotification", [options]);
+};
+
// Call this to set the application icon badge
PushNotification.prototype.setApplicationIconBadgeNumber = function(successCallback, errorCallback, badge) {
if (errorCallback == null) { errorCallback = function() {}}