UNPKG

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