UNPKG

57.6 kBMarkdownView Raw
1- [Overview](#overview)
2 - [Foreground Events](#push-message-arrives-with-app-in-foreground)
3 - [Background Events](#push-message-arrives-with-app-in-background)
4 - [Tap Events](#user-clicks-on-notification-in-notification-center)
5- [Android Behaviour](#android-behaviour)
6 - [Notification vs Data Payloads](#notification-vs-data-payloads)
7 - [Localization](#localization)
8 - [Images](#images)
9 - [Sound](#sound)
10 - [Stacking](#stacking)
11 - [Inbox Stacking](#inbox-stacking)
12 - [Action Buttons](#action-buttons)
13 - [In Line Replies](#in-line-replies)
14 - [Led in Notifications](#led-in-notifications)
15 - [Vibration Pattern in Notifications](#vibration-pattern-in-notifications)
16 - [Priority in Notifications](#priority-in-notifications)
17 - [Picture Messages](#picture-messages)
18 - [Background Notifications](#background-notifications)
19 - [Use of content_available: true](#use-of-content-available-true)
20 - [Caching](#caching)
21 - [Huawei and Xiaomi Phones](#huawei-and-xiaomi-phones)
22 - [Application force closed](#application-force-closed)
23 - [Visibility](#visibility-of-notifications)
24 - [Badges](#badges)
25 - [Support for Twilio Notify](#support-for-twilio-notify)
26 - [Notification ID](#notification-id)
27- [iOS Behaviour](#ios-behaviour)
28 - [Sound](#sound-1)
29 - [Background Notifications](#background-notifications-1)
30 - [Action Buttons](#action-buttons-1)
31 - [Action Buttons using GCM on iOS](#action-buttons-using-gcm-on-ios)
32 - [GCM and Additional Data](#gcm-and-additional-data)
33- [Windows Behaviour](#windows-behaviour)
34 - [Notifications](#notifications)
35 - [Setting Toast Capable Option for Windows](#setting-toast-capable-option-for-windows)
36 - [Disabling the default processing of notifications by Windows](#disabling-the-default-processing-of-notifications-by-windows)
37 - [Background Notifications](#background-notifications-2)
38
39
40# Overview
41
42The following flowchart attempts to give you a picture of what happens when a push message arrives on your device when you have an app using phonegap-plugin-push.
43
44![push-flowchart](https://cloud.githubusercontent.com/assets/353180/15752003/36b80afa-28ba-11e6-818b-c6f5f2966d8f.png)
45
46## Push message arrives with app in foreground
47
48- The push plugin receives the data from the remote push service and calls all of your `notification` event handlers.
49- The message is *not* displayed in the devices notification center as that is not normal behaviour for Android or iOS.
50
51## Push message arrives with app in background
52
53- The push plugin receives the data from the remote push service and checks to see if there is a title or message in the data received. If there is then the message will be displayed in the devices notification center.
54- Then the push plugin checks to see if the app is running. If the user has killed the application then no further processing of the push data will occur.
55- If the app is running in the background the push plugin then checks to see if `content-available` exists in the push data.
56- If `content-available` is set to `1` then the plugin calls all of your `notification` event handlers.
57
58## User clicks on notification in notification center
59
60- The app starts.
61- Then the plugin calls all of your `notification` event handlers.
62
63> Note: if the push payload contained `content-available: 1` then your `notification` event handler has already been called. It is up to you to handle the double event.
64
65Some ways to handle this *double* event are:
66
67- don't include title/message in the push so it doesn't show up in the shader.
68- send two pushes, one to be processed in the background the other to show up in the shade.
69- include a unique ID in your push so you can check to see if you've already processed this event.
70
71# Android Behaviour
72
73## Notification vs Data Payloads
74
75Notifications behave differently depending on the foreground/background state of the receiving app and the payload you send to the app.
76
77For instance if you send the following payload:
78
79```
80{
81 "notification": {
82 "title": "Test Notification",
83 "body": "This offer expires at 11:30 or whatever",
84 "notId": 10
85 }
86}
87```
88
89When your app is in the foreground any `on('notification')` handlers you have registered will be called. However if your app is in the background the notification will show up in the system tray. Clicking on the notification in the system tray will start the app but your `on('notification')` handler will not be called as messages with only `notification` payloads will not cause the plugins `onMessageReceived` method to be called.
90
91If you send a payload with a mix of `notification` & `data` objects like this:
92
93```
94{
95 "notification": {
96 "title": "Test Notification",
97 "body": "This offer expires at 11:30 or whatever",
98 "notId": 10
99 },
100 "data" : {
101 "surveyID": "ewtawgreg-gragrag-rgarhthgbad"
102 }
103}
104```
105
106When your app is in the foreground any `on('notification')` handlers you have registered will be called. If your app is in the background the notification will show up in the system tray. Clicking on the notification in the system tray will start the app and your `on('notification')` handler will not be called as messages with only `notification` payloads will not cause the plugins `onMessageReceived` method to be called.
107
108My recommended format for your push payload when using this plugin (while it differs from Google's docs) works 100% of the time:
109
110```
111{
112 "data" : {
113 "title": "Test Notification",
114 "body": "This offer expires at 11:30 or whatever",
115 "notId": 10,
116 "surveyID": "ewtawgreg-gragrag-rgarhthgbad"
117 }
118}
119```
120
121When your app is in the foreground any `on('notification')` handlers you have registered will be called. If your app is in the background the notification will show up in the system tray. Clicking on the notification in the system tray will start the app and your `on('notification')` handler will be called and the event received by your `on('notification')` handler will get the following data:
122
123```
124{
125 "message": "This offer expires at 11:30 or whatever",
126 "title": "Test Notification",
127 "additionalData": {
128 "surveyID": "ewtawgreg-gragrag-rgarhthgbad"
129 }
130}
131```
132
133## Localization
134
135Plugin supported localization from resources for: title, message and summaryText.
136
137You may use simple link to locale constant.
138
139```javascript
140{
141 "registration_ids": ["my device id"],
142 "data": {
143 "title": {"locKey": "push_app_title"},
144 "message": "Simple non-localizable text for message!"
145 }
146}
147```
148
149Or use localization with formatted constants.
150
151```javascript
152{
153 "registration_ids": ["my device id"],
154 "data": {
155 "title": {"locKey": "push_app_title"},
156 "message": {"locKey": "push_message_fox", "locData": ["fox", "dog"]}
157 }
158}
159```
160
161Here is an example using fcm-node that sends the above JSON:
162
163```javascript
164var FCM = require('fcm-node');
165// Replace these with your own values.
166var apiKey = "replace with API key";
167var deviceID = "my device id";
168var fcm = new FCM(apiKey);
169
170var message = {
171 to: deviceID,
172 data: {
173 title: {"locKey": "push_app_title"},
174 message: 'Simple non-localizable text for message!'
175 // Constant with formatted params
176 // message: {"locKey": "push_message_fox", "locData": ["fox", "dog"]});
177 }
178};
179
180fcm.send(message, function(err, response){
181 if (err) {
182 console.log(err);
183 console.log("Something has gone wrong!");
184 } else {
185 console.log("Successfully sent with response: ", response);
186 }
187});
188```
189
190Localization must store in strings.xml
191
192```xml
193<string name="push_app_title">@string/app_name</string>
194<string name="push_message_fox">The quick brown %1$s jumps over the lazy %2$s</string>
195<string name="push_summary_text">%%n%% new message(s)</string>
196```
197
198## Images
199
200By default the icon displayed in your push notification will be your apps icon. So when you initialize the plugin like this:
201
202```javascript
203var push = PushNotification.init({
204 "android": {
205 },
206 "browser": {
207 pushServiceURL: 'http://push.api.phonegap.com/v1/push'
208 },
209 "ios": {
210 "alert": "true",
211 "badge": "true",
212 "sound": "true"
213 },
214 "windows": {}
215});
216```
217
218The result will look much like this:
219
220![2015-07-24 02 52 00](https://cloud.githubusercontent.com/assets/353180/8866899/2df00c3c-3190-11e5-8552-96201fb4424b.png)
221
222This is because Android now uses Material design and the default icon for push will be completely white.
223
224In order to get a better user experience you can specify an alternate icon and background color to be shown when receiving a push notification. The code would look like this:
225
226```javascript
227var push = PushNotification.init({
228 "android": {
229 "icon": "phonegap",
230 "iconColor": "blue"
231 },
232 "browser": {
233 pushServiceURL: 'http://push.api.phonegap.com/v1/push'
234 },
235 "ios": {
236 "alert": "true",
237 "badge": "true",
238 "sound": "true"
239 },
240 "windows": {}
241});
242```
243
244Where *icon* is the name of an `.png` image file in the Android `res/drawable` folder. For example: `platforms/android/res/drawable/phonegap.png`
245Writing a hook to describe how to copy an image to the Android `res/drawable` folder is out of scope for this README but there is an [excellent tutorial](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/) that you can copy.
246
247*iconColor* is one of the supported formats #RRGGBB or #AARRGGBB or one of the following names: 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta', 'yellow', 'lightgray', 'darkgray', 'grey', 'lightgrey', 'darkgrey', 'aqua', 'fuchsia', 'lime', 'maroon', 'navy', 'olive', 'purple', 'silver', 'teal'. *iconColor* is supported on Android 5.0 and greater.
248
249Please follow the [Android icon design guidelines](https://www.google.com/design/spec/style/icons.html#) when creating your icon.
250
251![2015-07-24 02 46 58](https://cloud.githubusercontent.com/assets/353180/8866902/2df3276e-3190-11e5-842a-c8cd95615ab0.png)
252
253Additionally, each push can include a large icon which is used to personalize each push. The location of the image may one of three types.
254
255The first is the `res/drawable` folder in your app. This JSON sent from GCM:
256
257```javascript
258{
259 "registration_ids": ["my device id"],
260 "data": {
261 "title": "Large Icon",
262 "message": "Loaded from drawable folder",
263 "image": "twitter"
264 }
265}
266```
267
268Here is an example using fcm-node that sends the above JSON:
269
270```javascript
271var FCM = require('fcm-node');
272// Replace these with your own values.
273var apiKey = "replace with API key";
274var deviceID = "my device id";
275var fcm = new FCM(apiKey);
276
277var message = {
278 to: deviceID,
279 data: {
280 title: 'Large Icon',
281 message: 'Loaded from drawables folder.',
282 image: 'twitter'
283 }
284};
285
286fcm.send(message, function(err, response){
287 if (err) {
288 console.log(err);
289 console.log("Something has gone wrong!");
290 } else {
291 console.log("Successfully sent with response: ", response);
292 }
293});
294```
295
296Would look for the *twitter* image in the `res/drawable` folder and produce the following notification.
297
298![2015-07-24 02 34 41](https://cloud.githubusercontent.com/assets/353180/8866903/2df48028-3190-11e5-8176-fe8b3f7c5aab.png)
299
300The second is the *assets* folder in your app. This JSON sent from GCM:
301
302```javascript
303{
304 "registration_ids": ["my device id"],
305 "data": {
306 "title": "Large Icon",
307 "message": "Loaded from assets folder",
308 "image": "www/image/logo.png"
309 }
310}
311```
312
313Here is an example using fcm-node that sends the above JSON:
314
315```javascript
316var FCM = require('fcm-node');
317// Replace these with your own values.
318var apiKey = "replace with API key";
319var deviceID = "my device id";
320var fcm = new FCM(apiKey);
321
322var message = {
323 to: deviceID,
324 data: {
325 title: 'Large Icon',
326 message: 'Loaded from assets folder.',
327 image: 'www/image/logo.png'
328 }
329};
330
331fcm.send(message, function(err, response){
332 if (err) {
333 console.log(err);
334 console.log("Something has gone wrong!");
335 } else {
336 console.log("Successfully sent with response: ", response);
337 }
338});
339```
340
341Would look for the *logo.png* file in the assets/www/img folder. Since your apps www folder gets copied into the Android assets folder it is an excellent spot to store the images without needing to write a hook to copy them to the `res/drawable` folder. It produces the following notification.
342
343![2015-07-24 02 20 02](https://cloud.githubusercontent.com/assets/353180/8866901/2df19052-3190-11e5-8c16-a355c59209f3.png)
344
345
346The third is the remote *URL*. This JSON sent from GCM:
347
348```javascript
349{
350 "registration_ids": ["my device id"],
351 "data": {
352 "title": "Large Icon",
353 "message": "Loaded from URL",
354 "image": "https://dl.dropboxusercontent.com/u/887989/antshot.png"
355 }
356}
357```
358
359Here is an example using fcm-node that sends the above JSON:
360
361```javascript
362var FCM = require('fcm-node');
363// Replace these with your own values.
364var apiKey = "replace with API key";
365var deviceID = "my device id";
366var fcm = new FCM(apiKey);
367
368var message = {
369 to: deviceID,
370 data: {
371 title: 'Large Icon',
372 message: 'Loaded from URL',
373 image: 'https://dl.dropboxusercontent.com/u/887989/antshot.png'
374 }
375};
376
377fcm.send(message, function(err, response){
378 if (err) {
379 console.log(err);
380 console.log("Something has gone wrong!");
381 } else {
382 console.log("Successfully sent with response: ", response);
383 }
384});
385```
386
387Produces the following notification.
388
389![2015-07-24 02 17 55](https://cloud.githubusercontent.com/assets/353180/8866900/2df0ab06-3190-11e5-9a81-fdb85bb0f5a4.png)
390
391Finally the Material UI guidelines recommend using a circular icon for the large icon if the subject of the image is a person. This JSON sent from GCM:
392
393```javascript
394{
395 "registration_ids": ["my device id"],
396 "data": {
397 "title": "Large Circular Icon",
398 "message": "Loaded from URL",
399 "image": "https://pbs.twimg.com/profile_images/837060031895896065/VHIQ4oUf_400x400.jpg",
400 "image-type": "circle"
401 }
402}
403```
404
405Here is an example using node-gcm that sends the above JSON:
406
407```javascript
408var gcm = require('node-gcm');
409// Replace these with your own values.
410var apiKey = "replace with API key";
411var deviceID = "my device id";
412var service = new gcm.Sender(apiKey);
413var message = new gcm.Message();
414message.addData('title', 'Large Circular Icon');
415message.addData('message', 'Loaded from URL');
416message.addData('image', 'https://pbs.twimg.com/profile_images/837060031895896065/VHIQ4oUf_400x400.jpg');
417message.addData('image-type', 'circular');
418service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) {
419 if(err) console.error(err);
420 else console.log(response);
421});
422```
423
424Produces the following notification.
425
426![screenshot_20170308-214947](https://cloud.githubusercontent.com/assets/353180/23733917/902a4650-0449-11e7-924e-d45a38030c74.png)
427
428## Sound
429
430For Android there are three special values for sound you can use. The first is `default` which will play the phones default notification sound.
431
432```javascript
433{
434 "registration_ids": ["my device id"],
435 "data": {
436 "title": "Default",
437 "message": "Plays default notification sound",
438 "soundname": "default"
439 }
440}
441```
442
443Then second is `ringtone` which will play the phones default ringtone sound.
444
445```javascript
446{
447 "registration_ids": ["my device id"],
448 "data": {
449 "title": "Ringtone",
450 "message": "Plays default ringtone sound",
451 "soundname": "ringtone"
452 }
453}
454```
455The third is the empty string which will cause for the playing of sound to be skipped.
456
457```javascript
458{
459 "registration_ids": ["my device id"],
460 "data": {
461 "title": "Silece",
462 "message": "Skips playing any sound",
463 "soundname": ""
464 }
465}
466```
467
468In order for your your notification to play a custom sound you will need to add the files to your Android project's `res/raw` directory. Then send the follow JSON from GCM:
469
470```javascript
471{
472 "registration_ids": ["my device id"],
473 "data": {
474 "title": "Sound Test",
475 "message": "Loaded res/raw",
476 "soundname": "test"
477 }
478}
479```
480
481Here is an example using fcm-node that sends the above JSON:
482
483```javascript
484var FCM = require('fcm-node');
485// Replace these with your own values.
486var apiKey = "replace with API key";
487var deviceID = "my device id";
488var fcm = new FCM(apiKey);
489
490var message = {
491 to: deviceID,
492 data: {
493 title: 'Sound Test',
494 message: 'Loaded res/raw',
495 soundname: 'test'
496 }
497};
498
499fcm.send(message, function(err, response){
500 if (err) {
501 console.log(err);
502 console.log("Something has gone wrong!");
503 } else {
504 console.log("Successfully sent with response: ", response);
505 }
506});
507```
508
509*Note:* when you specify the custom sound file name omit the file's extension.
510
511## Stacking
512
513By default when using this plugin on Android each notification that your app receives will replace the previous notification in the shade.
514
515If you want to see multiple notifications in the shade you will need to provide a notification ID as part of the push data sent to the app. For instance if you send:
516
517```javascript
518{
519 "registration_ids": ["my device id"],
520 "data": {
521 "title": "Test Push",
522 "message": "Push number 1"
523 }
524}
525```
526
527Here is an example using fcm-node that sends the above JSON:
528
529```javascript
530var FCM = require('fcm-node');
531// Replace these with your own values.
532var apiKey = "replace with API key";
533var deviceID = "my device id";
534var fcm = new FCM(apiKey);
535
536var message = {
537 to: deviceID,
538 data: {
539 title: 'Test Push',
540 message: 'Push number 1'
541 }
542};
543
544fcm.send(message, function(err, response){
545 if (err) {
546 console.log(err);
547 console.log("Something has gone wrong!");
548 } else {
549 console.log("Successfully sent with response: ", response);
550 }
551});
552```
553
554Followed by:
555
556```javascript
557{
558 "registration_ids": ["my device id"],
559 "data": {
560 "title": "Test Push",
561 "message": "Push number 2"
562 }
563}
564```
565
566Here is an example using fcm-node that sends the above JSON:
567
568```javascript
569var FCM = require('fcm-node');
570// Replace these with your own values.
571var apiKey = "replace with API key";
572var deviceID = "my device id";
573var fcm = new FCM(apiKey);
574
575var message = {
576 to: deviceID,
577 data: {
578 title: 'Test Push',
579 message: 'Push number 2'
580 }
581};
582
583fcm.send(message, function(err, response){
584 if (err) {
585 console.log(err);
586 console.log("Something has gone wrong!");
587 } else {
588 console.log("Successfully sent with response: ", response);
589 }
590});
591```
592
593You will only see "Push number 2" in the shade. However, if you send:
594
595```javascript
596{
597 "registration_ids": ["my device id"],
598 "data": {
599 "title": "Test Push",
600 "message": "Push number 1",
601 "notId": 1
602 }
603}
604```
605
606Here is an example using fcm-node that sends the above JSON:
607
608```javascript
609var FCM = require('fcm-node');
610// Replace these with your own values.
611var apiKey = "replace with API key";
612var deviceID = "my device id";
613var fcm = new FCM(apiKey);
614
615var message = {
616 to: deviceID,
617 data: {
618 title: 'Test Push',
619 message: 'Push number 1',
620 notId: 1
621 }
622};
623
624fcm.send(message, function(err, response){
625 if (err) {
626 console.log(err);
627 console.log("Something has gone wrong!");
628 } else {
629 console.log("Successfully sent with response: ", response);
630 }
631});
632```
633
634and:
635
636```javascript
637{
638 "registration_ids": ["my device id"],
639 "data": {
640 "title": "Test Push",
641 "message": "Push number 2",
642 "notId": 2
643 }
644}
645```
646
647Here is an example using fcm-node that sends the above JSON:
648
649```javascript
650var FCM = require('fcm-node');
651// Replace these with your own values.
652var apiKey = "replace with API key";
653var deviceID = "my device id";
654var fcm = new FCM(apiKey);
655
656var message = {
657 to: deviceID,
658 data: {
659 title: 'Test Push',
660 message: 'Push number 2',
661 notId: 2
662 }
663};
664
665fcm.send(message, function(err, response){
666 if (err) {
667 console.log(err);
668 console.log("Something has gone wrong!");
669 } else {
670 console.log("Successfully sent with response: ", response);
671 }
672});
673```
674
675You will see both "Push number 1" and "Push number 2" in the shade.
676
677## Inbox Stacking
678
679A better alternative to stacking your notifications is to use the inbox style to have up to 8 lines of notification text in a single notification. If you send the following JSON from GCM you will see:
680
681```javascript
682{
683 "registration_ids": ["my device id"],
684 "data": {
685 "title": "My Title",
686 "message": "My first message",
687 "style": "inbox",
688 "summaryText": "There are %n% notifications"
689 }
690}
691```
692
693Here is an example using fcm-node that sends the above JSON:
694
695```javascript
696var FCM = require('fcm-node');
697// Replace these with your own values.
698var apiKey = "replace with API key";
699var deviceID = "my device id";
700var fcm = new FCM(apiKey);
701
702var message = {
703 to: deviceID,
704 data: {
705 title: 'My Title',
706 message: 'My first message',
707 style: 'inbox',
708 summaryText: 'There are %n% notifications'
709 }
710};
711
712fcm.send(message, function(err, response){
713 if (err) {
714 console.log(err);
715 console.log("Something has gone wrong!");
716 } else {
717 console.log("Successfully sent with response: ", response);
718 }
719});
720```
721
722It will produce a normal looking notification:
723
724![2015-08-25 14 11 27](https://cloud.githubusercontent.com/assets/353180/9468840/c9c5d43a-4b11-11e5-814f-8dc995f47830.png)
725
726But, if you follow it up with subsequent notifications like:
727
728```javascript
729{
730 "registration_ids": ["my device id"],
731 "data": {
732 "title": "My Title",
733 "message": "My second message",
734 "style": "inbox",
735 "summaryText": "There are %n% notifications"
736 }
737}
738```
739
740Here is an example using fcm-node that sends the above JSON:
741
742```javascript
743var FCM = require('fcm-node');
744// Replace these with your own values.
745var apiKey = "replace with API key";
746var deviceID = "my device id";
747var fcm = new FCM(apiKey);
748
749var message = {
750 to: deviceID,
751 data: {
752 title: 'My Title',
753 message: 'My second message',
754 style: 'inbox',
755 summaryText: 'There are %n% notifications'
756 }
757};
758
759fcm.send(message, function(err, response){
760 if (err) {
761 console.log(err);
762 console.log("Something has gone wrong!");
763 } else {
764 console.log("Successfully sent with response: ", response);
765 }
766});
767```
768
769You will get an inbox view so you can display multiple notifications in a single panel.
770
771![2015-08-25 14 01 35](https://cloud.githubusercontent.com/assets/353180/9468727/2d658bee-4b11-11e5-90fa-248d54c8f3f6.png)
772
773If you use `%n%` in the `summaryText` of the JSON coming down from GCM it will be replaced by the number of messages that are currently in the queue.
774
775## Action Buttons
776
777Your notification can include a maximum of three action buttons. If you wish to include an icon along with the button name they must be placed in the `res/drawable` directory of your Android project. Then you can send the following JSON from GCM:
778
779```javascript
780{
781 "registration_ids": ["my device id"],
782 "data": {
783 "title": "AUX Scrum",
784 "message": "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.",
785 "actions": [
786 { "icon": "emailGuests", "title": "EMAIL GUESTS", "callback": "app.emailGuests", "foreground": true},
787 { "icon": "snooze", "title": "SNOOZE", "callback": "app.snooze", "foreground": false}
788 ]
789 }
790}
791```
792
793Here is an example using fcm-node that sends the above JSON:
794
795```javascript
796var FCM = require('fcm-node');
797// Replace these with your own values.
798var apiKey = "replace with API key";
799var deviceID = "my device id";
800var fcm = new FCM(apiKey);
801
802var message = {
803 to: deviceID,
804 data: {
805 title: 'AUX Scrum',
806 message: 'Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.',
807 actions: [
808 { icon: "emailGuests", title: "EMAIL GUESTS", callback: "app.emailGuests", foreground: true},
809 { icon: "snooze", title: "SNOOZE", callback: "app.snooze", foreground: false},
810 ]
811 }
812};
813
814fcm.send(message, function(err, response){
815 if (err) {
816 console.log(err);
817 console.log("Something has gone wrong!");
818 } else {
819 console.log("Successfully sent with response: ", response);
820 }
821});
822```
823
824This will produce the following notification in your tray:
825
826![action_combo](https://cloud.githubusercontent.com/assets/353180/9313435/02554d2a-44f1-11e5-8cd9-0aadd1e02b18.png)
827
828If your user clicks on the main body of the notification your app will be opened. However if they click on either of the action buttons the app will open (or start) and the specified JavaScript callback will be executed if there is a function defined, and if there isn't an event will be emitted with the callback name. In this case it is `app.emailGuests` and `app.snooze` respectively. If you set the `foreground` property to `true` the app will be brought to the front, if `foreground` is `false` then the callback is run without the app being brought to the foreground.
829
830### In Line Replies
831
832Android N introduces a new capability for push notifications, the in line reply text field. If you wish to get some text data from the user when the action button is called send the following type of payload:
833
834Your notification can include action buttons. If you wish to include an icon along with the button name they must be placed in the `res/drawable` directory of your Android project. Then you can send the following JSON from GCM:
835
836```javascript
837{
838 "registration_ids": ["my device id"],
839 "data": {
840 "title": "AUX Scrum",
841 "message": "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.",
842 "actions": [
843 { "icon": "emailGuests", "title": "EMAIL GUESTS", "callback": "app.emailGuests", "foreground": false, "inline": true },
844 { "icon": "snooze", "title": "SNOOZE", "callback": "app.snooze", "foreground": false}
845 ]
846 }
847}
848```
849
850Here is an example using fcm-node that sends the above JSON:
851
852```javascript
853var FCM = require('fcm-node');
854// Replace these with your own values.
855var apiKey = "replace with API key";
856var deviceID = "my device id";
857var fcm = new FCM(apiKey);
858
859var message = {
860 to: deviceID,
861 data: {
862 title: 'AUX Scrum',
863 message: 'Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.',
864 actions: [
865 { "icon": "emailGuests", "title": "EMAIL GUESTS", "callback": "app.emailGuests", "foreground": false, "inline": true},
866 { "icon": "snooze", "title": "SNOOZE", "callback": "app.snooze", "foreground": false},
867 ]
868 }
869};
870
871fcm.send(message, function(err, response){
872 if (err) {
873 console.log(err);
874 console.log("Something has gone wrong!");
875 } else {
876 console.log("Successfully sent with response: ", response);
877 }
878});
879```
880
881On Android N and greater when the user clicks on the Email Guests button they will see the following:
882
883![inline_reply](https://cloud.githubusercontent.com/assets/353180/17107608/f35c208e-525d-11e6-94de-a3590c6f500d.png)
884
885Then your app's `on('notification')` event handler will be called without the app being brought to the foreground and the event data would be:
886
887```
888{
889 "title": "AUX Scrum",
890 "message": "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.",
891 "additionalData": {
892 "inlineReply": "Sounds good",
893 "actions": [
894 {
895 "inline": true,
896 "callback": "app.accept",
897 "foreground": false,
898 "title": "Accept"
899 },
900 {
901 "icon": "snooze",
902 "callback": "app.reject",
903 "foreground": false,
904 "title": "Reject"
905 }
906 ],
907 "actionCallback": "app.accept",
908 "coldstart": false,
909 "collapse_key": "do_not_collapse",
910 "foreground": false
911 }
912}
913```
914
915and the text data that the user typed would be located in `data.additionalData.inlineReply`.
916
917**Note:** On Android M and earlier the above in line behavior is not supported. As a fallback when `inline` is set to `true` the `foreground` setting will be changed to the default `true` setting. This allows your app to be launched from a closed state into the foreground where any behavior desired as a result of the user selecting the in line reply action button can be handled through the associated `callback`.
918
919#### Attributes
920
921Attribute | Type | Default | Description
922--------- | ---- | ------- | -----------
923`icon` | `string` | | Optional. The name of a drawable resource to use as the small-icon. The name should not include the extension.
924`title` | `string` | | Required. The label to display for the action button.
925`callback` | `string` | | Required. The function to be executed or the event to be emitted when the action button is pressed. The function must be accessible from the global namespace. If you provide `myCallback` then it amounts to calling `window.myCallback`. If you provide `app.myCallback` then there needs to be an object call `app`, with a function called `myCallback` accessible from the global namespace, i.e. `window.app.myCallback`. If there isn't a function with the specified name an event will be emitted with the callback name.
926`foreground` | `boolean` | `true` | Optional. Whether or not to bring the app to the foreground when the action button is pressed.
927`inline` | `boolean` | `false` | Optional. Whether or not to provide a quick reply text field to the user when the button is clicked.
928
929## Led in Notifications
930
931You can use a Led notifcation and choose the color of it. Just add a `ledColor` field in your notification in the ARGB format array:
932
933```javascript
934{
935 "registration_ids": ["my device id"],
936 "data": {
937 "title": "Green LED",
938 "message": "This is my message with a Green LED",
939 "ledColor": [0, 0, 255, 0]
940 }
941}
942```
943
944Here is an example using fcm-node that sends the above JSON:
945
946```javascript
947var FCM = require('fcm-node');
948// Replace these with your own values.
949var apiKey = "replace with API key";
950var deviceID = "my device id";
951var fcm = new FCM(apiKey);
952
953var message = {
954 to: deviceID,
955 data: {
956 title: 'Green LED',
957 message: 'This is my message with a Green LED',
958 ledColor: [0, 0, 255, 0]
959 }
960};
961
962fcm.send(message, function(err, response){
963 if (err) {
964 console.log(err);
965 console.log("Something has gone wrong!");
966 } else {
967 console.log("Successfully sent with response: ", response);
968 }
969});
970```
971
972## Vibration Pattern in Notifications
973
974You can set a Vibration Pattern for your notifications. Just add a `vibrationPattern` field in your notification:
975
976```javascript
977{
978 "registration_ids": ["my device id"],
979 "data": {
980 "title": "Vibration Pattern",
981 "message": "Device should wait for 2 seconds, vibrate for 1 second then be silent for 500 ms then vibrate for 500 ms",
982 "vibrationPattern": [2000, 1000, 500, 500]
983 }
984}
985```
986
987Here is an example using fcm-node that sends the above JSON:
988
989```javascript
990var FCM = require('fcm-node');
991// Replace these with your own values.
992var apiKey = "replace with API key";
993var deviceID = "my device id";
994var fcm = new FCM(apiKey);
995
996var message = {
997 to: deviceID,
998 data: {
999 title: 'Vibration Pattern',
1000 message: 'Device should wait for 2 seconds, vibrate for 1 second then be silent for 500 ms then vibrate for 500 ms',
1001 vibrationPattern: [2000, 1000, 500, 500]
1002 }
1003};
1004
1005fcm.send(message, function(err, response){
1006 if (err) {
1007 console.log(err);
1008 console.log("Something has gone wrong!");
1009 } else {
1010 console.log("Successfully sent with response: ", response);
1011 }
1012});
1013```
1014
1015## Priority in Notifications
1016
1017You can set a priority parameter for your notifications. This priority value determines where the push notification will be put in the notification shade. Low-priority notifications may be hidden from the user in certain situations, while the user might be interrupted for a higher-priority notification. Add a `priority` field in your notification. -2: minimum, -1: low, 0: default , 1: high, 2: maximum priority.
1018
1019```javascript
1020{
1021 "registration_ids": ["my device id"],
1022 "data": {
1023 "title": "This is a maximum priority Notification",
1024 "message": "This notification should appear in front of all others",
1025 "priority": 2
1026 }
1027}
1028```
1029
1030Here is an example using fcm-node that sends the above JSON:
1031
1032```javascript
1033var FCM = require('fcm-node');
1034// Replace these with your own values.
1035var apiKey = "replace with API key";
1036var deviceID = "my device id";
1037var fcm = new FCM(apiKey);
1038
1039var message = {
1040 to: deviceID,
1041 data: {
1042 title: 'This is a maximum priority Notification',
1043 message: 'This notification should appear in front of all others',
1044 priority: 2
1045 }
1046};
1047
1048fcm.send(message, function(err, response){
1049 if (err) {
1050 console.log(err);
1051 console.log("Something has gone wrong!");
1052 } else {
1053 console.log("Successfully sent with response: ", response);
1054 }
1055});
1056```
1057
1058Do not confuse this with the GCM option of setting the [delivery priority of the message](https://developers.google.com/cloud-messaging/concept-options#setting-the-priority-of-a-message). Which is used by GCM to tell the device whether or not it should wake up to deal with the message.
1059
1060## Picture Messages
1061
1062Perhaps you want to include a large picture in the notification that you are sending to your users. Luckily you can do that too by sending the following JSON from GCM.
1063
1064```javascript
1065{
1066 "registration_ids": ["my device id"],
1067 "data": {
1068 "title": "Big Picture",
1069 "message": "This is my big picture message",
1070 "style": "picture",
1071 "picture": "http://36.media.tumblr.com/c066cc2238103856c9ac506faa6f3bc2/tumblr_nmstmqtuo81tssmyno1_1280.jpg",
1072 "summaryText": "The internet is built on cat pictures"
1073 }
1074}
1075```
1076
1077Here is an example using fcm-node that sends the above JSON:
1078
1079```javascript
1080var FCM = require('fcm-node');
1081// Replace these with your own values.
1082var apiKey = "replace with API key";
1083var deviceID = "my device id";
1084var fcm = new FCM(apiKey);
1085
1086var message = {
1087 to: deviceID,
1088 data: {
1089 title: 'Big Picture',
1090 message: 'This is my big picture message',
1091 picture: 'http://36.media.tumblr.com/c066cc2238103856c9ac506faa6f3bc2/tumblr_nmstmqtuo81tssmyno1_1280.jpg',
1092 summaryText: 'The internet is built on cat pictures'
1093 }
1094};
1095
1096fcm.send(message, function(err, response){
1097 if (err) {
1098 console.log(err);
1099 console.log("Something has gone wrong!");
1100 } else {
1101 console.log("Successfully sent with response: ", response);
1102 }
1103});
1104```
1105
1106This will produce the following notification in your tray:
1107
1108![2015-08-25 16 08 00](https://cloud.githubusercontent.com/assets/353180/9472260/3655fa7a-4b22-11e5-8d87-20528112de16.png)
1109
1110> Note: When the notification arrives you will see the title and message like normally. You will only see the picture when the notification is expanded. Once expanded not only will you see the picture but the message portion will disappear and you'll see the summary text portion.
1111
1112## Background Notifications
1113
1114On Android if you want your `on('notification')` event handler to be called when your app is in the background it is relatively simple.
1115
1116First the JSON you send from GCM will need to include `"content-available": "1"`. This will tell the push plugin to call your `on('notification')` event handler no matter what other data is in the push notification.
1117
1118```javascript
1119{
1120 "registration_ids": ["my device id"],
1121 "data": {
1122 "title": "Test Push",
1123 "message": "Push number 1",
1124 "info": "super secret info",
1125 "content-available": "1"
1126 }
1127}
1128```
1129
1130Here is an example using fcm-node that sends the above JSON:
1131
1132```javascript
1133var FCM = require('fcm-node');
1134// Replace these with your own values.
1135var apiKey = "replace with API key";
1136var deviceID = "my device id";
1137var fcm = new FCM(apiKey);
1138
1139var message = {
1140 "to": deviceID,
1141 "data": {
1142 "title": 'Test Push',
1143 "message": 'Push number 1',
1144 "info": 'super secret info',
1145 "content-available": '1'
1146 }
1147};
1148
1149fcm.send(message, function(err, response){
1150 if (err) {
1151 console.log(err);
1152 console.log("Something has gone wrong!");
1153 } else {
1154 console.log("Successfully sent with response: ", response);
1155 }
1156});
1157```
1158
1159or if you want the payload to be delivered directly to your app without anything showing up in the notification center omit the tite/message from the payload like so:
1160
1161
1162```javascript
1163{
1164 "registration_ids": ["my device id"],
1165 "data": {
1166 "info": "super secret info",
1167 "content-available": "1"
1168 }
1169}
1170```
1171
1172Here is an example using fcm-node that sends the above JSON:
1173
1174```javascript
1175var FCM = require('fcm-node');
1176// Replace these with your own values.
1177var apiKey = "replace with API key";
1178var deviceID = "my device id";
1179var fcm = new FCM(apiKey);
1180
1181var message = {
1182 "to": deviceID,
1183 "data": {
1184 "info": 'super secret info',
1185 "content-available": '1'
1186 }
1187};
1188
1189fcm.send(message, function(err, response){
1190 if (err) {
1191 console.log(err);
1192 console.log("Something has gone wrong!");
1193 } else {
1194 console.log("Successfully sent with response: ", response);
1195 }
1196});
1197```
1198
1199If do not want this type of behaviour just omit `"content-available": 1` from your push data and your `on('notification')` event handler will not be called.
1200
1201### Use of content_available: true
1202
1203The [GCM docs](https://developers.google.com/cloud-messaging/http-server-ref#downstream-http-messages-json) will tell you to send a data payload of:
1204
1205```javascript
1206{
1207 "registration_ids": ["my device id"],
1208 "content_available": true,
1209 "data": {
1210 "title": "Test Push",
1211 "message": "Push number 1",
1212 "info": "super secret info",
1213 }
1214}
1215```
1216
1217Where the `content_available` property is part of the main payload object. Setting the property in this part of the payload will result in the PushPlugin not getting the data correctly. Setting `content_available: true` will cause the Android OS to handle the push payload for you and not pass the data to the PushPlugin.
1218
1219Instead move `content_available: true` into the `data` object of the payload. The property name changes slightly to use a `-` instead of an `_`. So, `content_available` becomes `content-available` and `true` becomes `1` as per the example below:
1220
1221```javascript
1222{
1223 "registration_ids": ["my device id"],
1224 "data": {
1225 "title": "Test Push",
1226 "message": "Push number 1",
1227 "info": "super secret info",
1228 "content-available": "1"
1229 }
1230}
1231```
1232
1233### Huawei and Xiaomi Phones
1234
1235These phones have a particular quirk that when the app is force closed that you will no longer be able to receive notifications until the app is restarted. In order for you to receive background notifications:
1236
1237- On your Huawei device go to Settings > Protected apps > check "My App" where.
1238- On your Xiaomi make sure your phone has the "Auto-start" property enabled for your app.
1239- On your Asus make sure your phone has the "Auto-start" property enabled for your app.
1240
1241### Application force closed
1242
1243In order to take advantage of this feature you will need to be using cordova-android 6.0.0 or higher. In order to check if the change has been properly applied look at `platforms/android/**/MainActivity.java`. You should see an `onCreate` method that looks like this:
1244
1245```java
1246@Override
1247public void onCreate(Bundle savedInstanceState)
1248{
1249 super.onCreate(savedInstanceState);
1250
1251 // enable Cordova apps to be started in the background
1252 Bundle extras = getIntent().getExtras();
1253 if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
1254 moveTaskToBack(true);
1255 }
1256
1257 // Set by <content src="index.html" /> in config.xml
1258 loadUrl(launchUrl);
1259}
1260```
1261
1262If you don't see the `if` statement that checks for the appearance of `cdvStartInBackground` you will probably need to do:
1263
1264```
1265phonegap platform rm android
1266phonegap platform add android
1267phonegap build android
1268```
1269
1270This should add the correct code to the `MainActivity` class.
1271
1272If you add `force-start: 1` to the data payload the application will be restarted in background even if it was force closed.
1273
1274```javascript
1275{
1276 "registration_ids": ["my device id"],
1277 "data": {
1278 "title": "Force Start",
1279 "message": "This notification should restart the app",
1280 "force-start": 1
1281 }
1282}
1283```
1284
1285Here is an example using fcm-node that sends the above JSON:
1286
1287```javascript
1288var FCM = require('fcm-node');
1289// Replace these with your own values.
1290var apiKey = "replace with API key";
1291var deviceID = "my device id";
1292var fcm = new FCM(apiKey);
1293
1294var message = {
1295 to: deviceID,
1296 "data": {
1297 "title": 'Force Start',
1298 "message": 'This notification should restart the app',
1299 "force-start": '1'
1300 }
1301};
1302
1303fcm.send(message, function(err, response){
1304 if (err) {
1305 console.log(err);
1306 console.log("Something has gone wrong!");
1307 } else {
1308 console.log("Successfully sent with response: ", response);
1309 }
1310});
1311```
1312
1313### Caching
1314
1315By default, when a notification arrives and 'content-available' is set to '1', the plugin will try to deliver the data payload even if the app is not running. In that case, the payload is cached and may be delivered when the app is started again. To disable this behavior, you can set a `no-cache` flag in the notification payload. 0: caching enabled (default), 1: caching disabled.
1316
1317```javascript
1318{
1319 "registration_ids": ["my device id"],
1320 "data": {
1321 "title": "Push without cache",
1322 "message": "When the app is closed, this notification will not be cached",
1323 "content-available": "1",
1324 "no-cache": "1"
1325 }
1326}
1327```
1328
1329## Visibility of Notifications
1330
1331You can set a visibility parameter for your notifications. Just add a `visibility` field in your notification. -1: secret, 0: private (default), 1: public. `Secret` shows only the most minimal information, excluding even the notification's icon. `Private` shows basic information about the existence of this notification, including its icon and the name of the app that posted it. The rest of the notification's details are not displayed. `Public` Shows the notification's full content.
1332
1333```javascript
1334{
1335 "registration_ids": ["my device id"],
1336 "data": {
1337 "title": "This is a maximum public Notification",
1338 "message": "This notification should appear in front of all others",
1339 "visibility": 1
1340 }
1341}
1342```
1343
1344Here is an example using fcm-node that sends the above JSON:
1345
1346```javascript
1347var FCM = require('fcm-node');
1348// Replace these with your own values.
1349var apiKey = "replace with API key";
1350var deviceID = "my device id";
1351var fcm = new FCM(apiKey);
1352
1353var message = {
1354 to: deviceID,
1355 data: {
1356 title: 'This is a public Notification',
1357 message: 'You should be able to read this notification on your lock screen',
1358 visibility: 1
1359 }
1360};
1361
1362fcm.send(message, function(err, response){
1363 if (err) {
1364 console.log(err);
1365 console.log("Something has gone wrong!");
1366 } else {
1367 console.log("Successfully sent with response: ", response);
1368 }
1369});
1370```
1371
1372## Badges
1373
1374On Android not all launchers support badges. In order for us to set badges we use [ShortcutBadger](https://github.com/leolin310148/ShortcutBadger) in order to set the badge. Check out their website to see which launchers are supported.
1375
1376In order to set the badge number you will need to include the `badge` property in your push payload as below:
1377
1378```javascript
1379{
1380 "registration_ids": ["my device id"],
1381 "data": {
1382 "title": "Badge Test",
1383 "message": "Badges, we don't need no stinking badges",
1384 "badge": 7
1385 }
1386}
1387```
1388
1389Here is an example using fcm-node that sends the above JSON:
1390
1391```javascript
1392var FCM = require('fcm-node');
1393// Replace these with your own values.
1394var apiKey = "replace with API key";
1395var deviceID = "my device id";
1396var fcm = new FCM(apiKey);
1397
1398var message = {
1399 to: deviceID,
1400 data: {
1401 title: 'Badge Test',
1402 message: 'Badges, we don\'t need no stinking badges',
1403 badge: 7
1404 }
1405};
1406
1407fcm.send(message, function(err, response){
1408 if (err) {
1409 console.log(err);
1410 console.log("Something has gone wrong!");
1411 } else {
1412 console.log("Successfully sent with response: ", response);
1413 }
1414});
1415```
1416
1417## Support for Twilio Notify
1418
1419This plugin seamlessly supports payloads generated by Twilio Notify on Android. Specifically the parameters passed in to the Twilio REST API are available in the message payload passed to your app as follows:
1420
1421- `Title` --> `data.title`
1422- `Body` --> `data.message`
1423- `Sound` --> `data.sound`
1424
1425Here is an example request to Twilio REST API and the corresponding JSON received by your app.
1426
1427```
1428curl 'https://notify.twilio.com/v1/Services/IS1e928b239609199df31d461071fd3d23/Notifications' -X POST \
1429--data-urlencode 'Identity=Bob' \
1430--data-urlencode 'Body=Hello Bob! Twilio Notify + Phonegap is awesome!' \
1431--data-urlencode 'Title=Hello Bob!' \
1432--data-urlencode 'Sound=chime' \
1433-u [AccountSID]:[AuthToken]
1434```
1435
1436The JSON received by your app will comply with the standards described in the sections above:
1437
1438```javascript
1439{
1440 "registration_ids": ["my device id"],
1441 "data": {
1442 "title": "Hello Bob!",
1443 "message": "Hello Bob! Twilio Notify + Phonegap is awesome!",
1444 "sound": "chime"
1445 }
1446}
1447```
1448
1449Note: "sound" and "soundname" are equivalent and are considered to be the same by the plugin.
1450
1451## Notification ID
1452
1453When setting the notification ID or `notId` please make sure that you are not exceeding the [MAX_INT](https://developer.android.com/reference/java/lang/Integer.html#MAX_VALUE) value for Android. Using a value larger than MAX_INT will throw an exception which will be caught by the plugin and it will use a default value of `0`.
1454
1455This means you can't use the JavaScript's `Date.getMilliseconds()` or Java's `System.currentTimeMillis()` as they will give you a value greater than MAX_INT.
1456
1457# iOS Behaviour
1458
1459## Sound
1460
1461In order for your notification to play a custom sound you will need to add the files to root of your iOS project. The files must be in the proper format. See the [Local and Remote Notification Programming Guide](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/SupportingNotificationsinYourApp.html#//apple_ref/doc/uid/TP40008194-CH4-SW10) for more info on proper file formats and how to convert existing sound files.
1462
1463Then send the follow JSON from APNS:
1464
1465```javascript
1466{
1467 "aps": {
1468 "alert": "Test sound",
1469 "sound": "sub.caf"
1470 }
1471}
1472```
1473
1474If you want the default sound to play upon receipt of push use this payload:
1475
1476```
1477{
1478 "aps": {
1479 "alert": "Test sound",
1480 "sound": "default"
1481 }
1482}
1483```
1484
1485## Background Notifications
1486
1487On iOS if you want your `on('notification')` event handler to be called when your app is in the background you will need to do a few things.
1488
1489First the JSON you send from APNS will need to include `"content-available": 1` to the `aps` object. The `"content-available": 1` property in your push message is a signal to iOS to wake up your app and give it up to 30 seconds of background processing. If do not want this type of behaviour just omit `"content-available": 1` from your push data. As well you *should* set a `notId` property in the root of payload object. This is the parameter you pass to the `finish` method in order to tell the operating system that the processing of the push event is done.
1490
1491For instance the following JSON:
1492
1493```javascript
1494{
1495 "aps": {
1496 "alert": "Test background push",
1497 "content-available": 1
1498 },
1499 "notId": 1 // unique ID you generate
1500}
1501```
1502
1503will produce a notification in the notification shade and call your `on('notification')` event handler.
1504
1505**NOTE:** The `on('notification')` event handler will **not** be called if Background App Refresh is disabled on the user's iOS device. (Settings > General > Background App Refresh)
1506
1507However if you want your `on('notification')` event handler called but no notification to be shown in the shader you would omit the `alert` property and send the following JSON to APNS:
1508
1509```javascript
1510{
1511 "aps": {
1512 "data": "Test silent background push",
1513 "moredata": "Do more stuff",
1514 "content-available": 1
1515 },
1516 "notId": 2 // unique ID you generate
1517}
1518```
1519
1520That covers what you need to do on the server side to accept background pushes on iOS. However, it is critically important that you continue reading as there will be a change in your `on('notification')`. When you receive a background push on iOS you will be given 30 seconds of time in which to complete a task. If you spend longer than 30 seconds on the task the OS may decide that your app is misbehaving and kill it. In order to signal iOS that your `on('notification')` handler is done you will need to call the new `push.finish()` method.
1521
1522For example:
1523
1524```javascript
1525var push = PushNotification.init({
1526 "ios": {
1527 "sound": "true",
1528 "alert": "true",
1529 "badge": "true",
1530 "clearBadge": "true"
1531 }
1532});
1533
1534push.on('registration', function(data) {
1535 // send data.registrationId to push service
1536});
1537
1538
1539push.on('notification', function(data) {
1540 // do something with the push data
1541 // then call finish to let the OS know we are done
1542 push.finish(function() {
1543 console.log("processing of push data is finished");
1544 }, function() {
1545 console.log("something went wrong with push.finish for ID = " + data.additionalData.notId)
1546 }, data.additionalData.notId);
1547});
1548```
1549
1550It is absolutely critical that you call `push.finish()` when you have successfully processed your background push data.
1551
1552## Action Buttons
1553
1554Your notification can include action buttons. For iOS 8+ you must setup the possible actions when you initialize the plugin:
1555
1556```javascript
1557var push = PushNotification.init({
1558 "ios": {
1559 "sound": true,
1560 "alert": true,
1561 "badge": true,
1562 "categories": {
1563 "invite": {
1564 "yes": {
1565 "callback": "app.accept", "title": "Accept", "foreground": true, "destructive": false
1566 },
1567 "no": {
1568 "callback": "app.reject", "title": "Reject", "foreground": true, "destructive": false
1569 },
1570 "maybe": {
1571 "callback": "app.maybe", "title": "Maybe", "foreground": true, "destructive": false
1572 }
1573 },
1574 "delete": {
1575 "yes": {
1576 "callback": "app.doDelete", "title": "Delete", "foreground": true, "destructive": true
1577 },
1578 "no": {
1579 "callback": "app.cancel", "title": "Cancel", "foreground": true, "destructive": false
1580 }
1581 }
1582 }
1583 }
1584});
1585```
1586
1587You’ll notice that we’ve added a new parameter to the iOS object of our init code called categories. Each category is a named object, invite and delete in this case. These names will need to match the one you send via your payload to APNS if you want the action buttons to be displayed. Each category can have up to three buttons which must be labeled `yes`, `no` and `maybe`. In turn each of these buttons has four properties, `callback` the javascript function you want to call, `title` the label for the button, `foreground` whether or not to bring your app to the foreground and `destructive` which doesn’t actually do anything destructive it just colors the button red as a warning to the user that the action may be destructive.
1588
1589Just like with background notifications it is absolutely critical that you call `push.finish()` when you have successfully processed the button callback. For instance:
1590
1591```javascript
1592app.accept = function(data) {
1593 // do something with the notification data
1594
1595 push.finish(function() {
1596 console.log('accept callback finished');
1597 }, function() {
1598 console.log('accept callback failed');
1599 }, data.additionalData.notId);
1600};
1601```
1602
1603You may notice that the `finish` method now takes `success`, `failure` and `id` parameters. The `id` parameter let's the operating system know which background process to stop. You'll set it in the next step.
1604
1605Then you will need to set the `category` value in your `aps` payload to match one of the objects in the `categories` object. As well you *should* set a `notId` property in the root of payload object. This is the parameter you pass to the `finish` method in order to tell the operating system that the processing of the push event is done.
1606
1607```javascript
1608{
1609 "aps": {
1610 "alert": "This is a notification that will be displayed ASAP.",
1611 "category": "invite"
1612 },
1613 "notId": "1"
1614}
1615```
1616
1617This will produce the following notification in your tray:
1618
1619![push6-ios](https://cloud.githubusercontent.com/assets/353180/12754125/12d13020-c998-11e5-98b4-b245fda30490.png)
1620
1621If your users clicks on the main body of the notification your app will be opened. However if they click on either of the action buttons the app will open (or start) and the specified JavaScript callback will be executed.
1622
1623### Action Buttons using GCM on iOS
1624
1625If you are using GCM to send push messages on iOS you will need to send a different payload in order for the action buttons to be present in the notification shade. You'll need to use the `click-action` property in order to specify the category.
1626
1627```javascript
1628{
1629 "registration_ids": ["my device id"],
1630 "notification": {
1631 "title": "AUX Scrum",
1632 "body": "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.",
1633 "click-action": "invite"
1634 }
1635}
1636```
1637
1638## GCM and Additional Data
1639
1640GCM on iOS is a different animal. The way you send data via GCM on Android is like:
1641
1642```javascript
1643{
1644 "registration_ids": ["my device id"],
1645 "data": {
1646 "title": "My Title",
1647 "message": "My message",
1648 "key1": "data 1",
1649 "key2": "data 2"
1650 }
1651}
1652```
1653
1654will produce a `notification` event with the following data:
1655
1656```javascript
1657{
1658 "title": "My Title",
1659 "message": "My message",
1660 "additionalData": {
1661 "key1": "data 1",
1662 "key2": "data 2"
1663 }
1664}
1665```
1666
1667but in order for the same `notification` event you would need to send your push to GCM iOS in a slight different format:
1668
1669```javascript
1670{
1671 "registration_ids": ["my device id"],
1672 "notification": {
1673 "title": "My Title",
1674 "body": "My message"
1675 }
1676 "data": {
1677 "key1": "data 1",
1678 "key2": "data 2"
1679 }
1680}
1681```
1682
1683The `title` and `body` need to be in the `notification` part of the payload in order for the OS to pick them up correctly. Everything else should be in the `data` part of the payload.
1684
1685## GCM Messages Not Arriving
1686
1687For some users of the plugin they are unable to get messages sent via GCM to show up on their devices. If you are running into this issue try setting the `priority` of the message to `high` in the payload.
1688
1689```javascript
1690{
1691 "registration_ids": ["my device id"],
1692 "notification": {
1693 "title": "My Title",
1694 "body": "My message"
1695 },
1696 "priority": "high"
1697}
1698```
1699
1700# Windows Behaviour
1701
1702## Notifications
1703
1704The plugin supports all types of windows platform notifications namely [Tile, Toast, Badge and Raw](https://msdn.microsoft.com/en-us/library/windows/apps/Hh779725.aspx). The API supports the basic cases of the notification templates with title corresponding to the first text element and message corresponding to the second if title is present else the first one. The image corresponds to the first image element of the notification xml.
1705
1706The count is present only for the badge notification in which it represent the value of the notification which could be a number from 0-99 or a status glyph.
1707
1708For advanced templates and usage, the notification object is included in [`data.additionalData.pushNotificationReceivedEventArgs`](https://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.pushnotifications.pushnotificationreceivedeventargs).
1709
1710## Setting Toast Capable Option for Windows
1711
1712This plugin automatically sets the toast capable flag to be true for Cordova 5.1.1+. For lower versions, you must declare that it is Toast Capable in your app's manifest file.
1713
1714## Disabling the default processing of notifications by Windows
1715
1716The default handling can be disabled by setting the 'cancel' property in the notification object.
1717
1718```javascript
1719data.additionalData.pushNotificationReceivedEventArgs.cancel = true
1720```
1721
1722## Background Notifications
1723
1724On Windows, to trigger the on('notification') event handler when your app is in the background and it is launched through the push notification, you will have to include `activation` data in the payload of the notification. This is done by using the `launch` attribute, which can be any string that can be understood by the app. However it should not cause the XML payload to become invalid.
1725
1726If you do not include a launch attribute string, your app will be launched normally, as though the user had launched it from the Start screen, and the notification event handler won't be called.
1727
1728Here is an example of a sample toast notification payload containing the launch attribute:
1729
1730```xml
1731<toast launch="{&quot;myContext&quot;:&quot;12345&quot;}">
1732 <visual>
1733 <binding template="ToastImageAndText01">
1734 <image id="1" src="ms-appx:///images/redWide.png" alt="red graphic"/>
1735 <text id="1">Hello World!</text>
1736 </binding>
1737 </visual>
1738</toast>
1739```
1740
1741This launch attribute string is passed on to the app as data.launchArgs through the on('notification') handler. It's important to note that due to the Windows platform design, the other visual payload is not available to the handler on cold start. So notification attributes like message, title etc. which are available through the on('notification') handler when the app is running, won't be available for background notifications.