1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12 
13    End User License Agreement: www.juce.com/juce-6-licence
14    Privacy Policy: www.juce.com/juce-privacy-policy
15 
16    Or: You may also use this code under the terms of the GPL v3 (see
17    www.gnu.org/licenses).
18 
19    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21    DISCLAIMED.
22 
23   ==============================================================================
24 */
25 
26 #pragma once
27 
28 namespace juce
29 {
30 
31 /** Singleton class responsible for push notifications functionality. Both remote and
32     local notifications are supported. To get information about notifications,
33     register a listener on your application startup. It is best to register the
34     listener as soon as possible, because your application can be launched from
35     a push notification too.
36 
37     To send a local notification create an instance of Notification, fill the necessary
38     fields and call PushNotifications::sendLocalNotification(). When receiving local or
39     remote notifications, inspect the Notification's fields for notification details.
40     Bear in mind that some fields will not be available when receiving a remote
41     notification.
42 
43     @tags{GUI}
44 */
45 class JUCE_API PushNotifications    : private DeletedAtShutdown
46 {
47 public:
48    #ifndef DOXYGEN
49     JUCE_DECLARE_SINGLETON (PushNotifications, false)
50    #endif
51 
52     //==============================================================================
53     /** Represents a notification that can be sent or received. */
54     struct Notification
55     {
56         Notification() = default;
57         Notification (const Notification& other);
58 
59         /** Checks whether a given notification is correctly configured for a given OS. */
60         bool isValid() const noexcept;
61 
62         /** Represents an action on a notification that can be presented as a button or a text input.
63             On Android, each notification has its action specified explicitly, on iOS you configure an
64             allowed set of actions on startup and pack them into categories (see Settings).
65         */
66         struct Action
67         {
68             /** Controls the appearance of this action. */
69             enum Style
70             {
71                 button,                    /**< Show this action as a button. */
72                 text                       /**< Show this action as a text input field (on Android API 20 or higher is required). */
73             };
74 
75             /** @name Common fields */
76             /**@{*/
77             Style  style = button;
78             String title;                 /**< Required. the name of the action displayed to the user. */
79             String textInputPlaceholder;  /**< Optional: placeholder text for text input notification.
80                                                Note that it will be ignored if button style is used. */
81             var    parameters;            /**< Optional: additional parameters that can be passed. */
82             /**@}*/
83 
84             /** @name iOS only fields */
85             /**@{*/
86             String  identifier;                    /**< Required: unique identifier. This should be one of the
87                                                         identifiers set with requestPermissionsWithSettings(). */
88             bool    triggerInBackground = false;   /**< Whether the app can process the action in background. */
89             bool    destructive = false;           /**< Whether to display the action as destructive. */
90             String  textInputButtonText;           /**< Optional: Text displayed on text input notification
91                                                         button (from iOS 10 only).
92                                                         Note that it will be ignored if style is set to Style::button. */
93             /**@}*/
94 
95             /** @name Android only fields */
96             /**@{*/
97             String       icon;            /**< Optional: name of an icon file (without an extension) to be used for
98                                                          this action. This must be the name of one of the image
99                                                          files included into resources when exporting an Android project
100                                                          (see "Extra Android Raw Resources" setting in Projucer).
101                                                          Note that not all Android versions support an icon for an action, though
102                                                          it is recommended to provide it nevertheless. */
103 
104             StringArray allowedResponses; /**< Optional: a list of possible answers if the answer set is limited.
105                                                When left empty, then the user will be able to input any text. */
106             /**@}*/
107         };
108 
109         //==============================================================================
110         /** @name Common fields */
111         /**@{*/
112 
113         String identifier;   /**< Required: unique id that can be used to later dismiss the notification
114                                   (on iOS available from version 10). */
115 
116         String title;        /**< Required: the title of the notification, usually displayed in the first row. */
117         String body;         /**< Required: the content of the notification, usually displayed in the second row. */
118         String subtitle;     /**< Optional: additional text, that may be displayed e.g. in the third row or in the header
119                                   area. Note that on Android, depending on OS version, this may fight for
120                                   space with other components of the notification, so use this field
121                                   judiciously. On iOS available from version 10. On Android available from API 16. */
122 
123         String groupId;      /**< Optional: allows the OS to visually group, collapse, and expand a set of notifications,
124                                   note that OS may automatically group notifications if no groupId is specified.
125                                   Available on Android API 20 or above and iOS 10 or above. */
126 
127         int badgeNumber = 0; /**< Optional: on platforms that support it, can set a number this notification represents. */
128         URL soundToPlay;     /**< Optional: empty when the notification should be silent. When the name is set to
129                                   "default_os_sound", then a default sound will be used.
130 
131                                   For a custom sound on OSX, set the URL to the name of a sound file (preferably without
132                                   an extension) and place the sound file directly in bundle's "Resources" directory (you
133                                   can use "Xcode Resource" tickbox in Projucer to achieve that), i.e. it cannot be in a
134                                   subdirectory of "Resources" like "Resources/sound". Alternatively, if a sound file
135                                   cannot be found in bundle's "Resources" directory, the OS may look for the sound in the
136                                   following paths: "~/Library/Sounds", "/Library/Sounds", "/Network/Library/Sounds",
137                                   "/System/Library/Sounds".
138 
139                                   For a custom sound on iOS, set the URL to a relative path within your bundle, including
140                                   file extension. For instance, if your bundle contains "sounds" folder with "my_sound.caf"
141                                   file, then the URL should be "sounds/my_sound.caf".
142 
143                                   For a custom sound on Android, set URL to the name of a raw resource file
144                                   (without an extension) that was included when exporting an Android project in
145                                   Projucer (see "Extra Android Raw Resources" setting). */
146 
147         var properties;      /**< Optional: collection of additional properties that may be passed as a dictionary. */
148 
149         /**@}*/
150 
151         //==============================================================================
152         /** @name iOS only fields */
153         /**@{*/
154 
155         String category;                /**< Required: determines set of actions that will appear (as per setup done
156                                              in requestPermissionsWithSettings()). */
157         double triggerIntervalSec = 0.; /**< Optional: specifies number of seconds before the notification should trigger. */
158         bool   repeat = false;          /**< Optional: allows the notification to continuously retrigger after
159                                              triggerIntervalSec seconds. Available from iOS 10. */
160 
161         /**@}*/
162 
163         //==============================================================================
164         /** @name Android only fields */
165         /**@{*/
166 
167         String icon;             /**< Required: name of an icon file (without an extension) to be used for
168                                                 this notification. This must be the name of one of the image
169                                                 files included into resources when exporting an Android project
170                                                 (see "Extra Android Raw Resources" setting in Projucer). */
171 
172         String channelId;       /**< Required for Android API level 26 or above: specifies notification channel id. Refer to
173                                      setupChannels(). Ignored on earlier Android versions. */
174 
175         Image largeIcon;        /**< Optional: an additional large icon displayed in the notification content view. */
176 
177         String tickerText;      /**< Optional: ticker text used for accessibility services. */
178 
179         Array<Action> actions;  /**< Optional: actions associated with the notification. Note that the OS may allow only a limited
180                                      number of actions to be presented, so always present most important actions first.
181                                      Available from Android API 16 or above. */
182 
183         /** Used to represent a progress of some operation. */
184         struct Progress
185         {
186             int  max = 0;               /**< Max possible value of a progress. A typical usecase is to set max to 100 and increment
187                                              current's value as percentage complete. */
188             int  current = 0;           /**< Current progress value, should be from 0 to max. */
189             bool indeterminate = false; /**< If true, then the progress represents a continuing activity indicator with ongoing
190                                              animation and no numeric value. */
191         };
192 
193         Progress progress;       /**< Optional: set to default (0, 0, false), to disable progress display. */
194 
195         /** Metadata that can be used by the OS to better handle the notification, depending on its priority. */
196         enum Type
197         {
198             unspecified,       /**< Category not set. */
199             alarm,             /**< Alarm or timer. */
200             call,              /**< Incoming voice/video call or similar. */
201             email,             /**< Async message like email. */
202             error,             /**< Error in background operation or authentication status. */
203             event,             /**< Calendar event. */
204             message,           /**< Incoming message (sms, instant message etc.). */
205             taskProgress,      /**< Progress for a long-running background operation. */
206             promo,             /**< Promotion or advertisement. */
207             recommendation,    /**< Specific, single thing related recommendation. */
208             reminder,          /**< User-scheduled reminder. */
209             service,           /**< Running background service. */
210             social,            /**< Social network or sharing update. */
211             status,            /**< Ongoing information about device or contextual status. */
212             system,            /**< System or device status update. */
213             transport          /**< Media transport control for playback. */
214         };
215 
216         /** Metadata used as a hint to the OS about the priority of the notification. */
217         enum Priority
218         {
219             veryLow  = -2,
220             low      = -1,
221             medium   =  0,
222             high     =  1,
223             veryHigh =  2
224         };
225 
226         String person;               /**< Optional: additional metadata used as a hint to OS that a notification is
227                                           related to a specific person. Can be useful for instance messaging apps.
228                                           Available from Android API 21 or above. */
229 
230         Type type = unspecified;     /**< Optional. Available from Android API 21 or above. */
231         Priority priority = medium;  /**< Optional. Available from Android API 16 or above. */
232 
233         /** Describes how to show the notification when the screen is locked. Available from Android API 21 or above. */
234         enum LockScreenAppearance
235         {
236             dontShow       = -1,  /**< The notification is not allowed on the lock screen */
237             showPartially  =  0,  /**< Only some information is allowed on the lock screen */
238             showCompletely =  1   /**< The entire notification is allowed on the lock screen */
239         };
240 
241         LockScreenAppearance lockScreenAppearance = showPartially;  /**< Optional. */
242 
243         std::unique_ptr<Notification> publicVersion; /**< Optional: if you set lockScreenAppearance to showPartially,
244                                                           then you can provide "public version" of your notification
245                                                           that will be displayed on the lock screen. This way you can
246                                                           control what information is visible when the screen is locked. */
247 
248         String groupSortKey;         /**< Optional: Used to order notifications within the same group. Available from Android API 20 or above. */
249         bool groupSummary = false;   /**< Optional: if true, then this notification will be a group summary of the group set with groupId.
250                                                     Available from Android API 20 or above. */
251 
252         Colour accentColour;  /**< Optional: sets accent colour. The default colour will be used if accentColour is not set.
253                                              Available from Android API 21 or above. */
254         Colour ledColour;     /**< Optional: Sets the led colour. The hardware will do its best to approximate the colour.
255                                    The default colour will be used if ledColour is not set. */
256 
257         /** Allows to control the time the device's led is on and off. */
258         struct LedBlinkPattern
259         {
260             int msToBeOn  = 0;   /**< The led will be on for the given number of milliseconds, after which it will turn off. */
261             int msToBeOff = 0;   /**< The led will be off for the given number of milliseconds, after which it will turn on. */
262         };
263 
264         LedBlinkPattern ledBlinkPattern; /**< Optional. */
265 
266         Array<int> vibrationPattern;  /**< Optional: sets the vibration pattern in milliseconds. The first value indicates how long
267                                            to wait until vibration starts. The second value indicates how long to vibrate. The third
268                                            value will say how long to not vibrate and so on. For instance, if the pattern is:
269                                            1000, 2000, 3000, 4000 - then one second after receiving a notification the device will
270                                            vibrate for two seconds, followed by 3 seconds of no vibration and finally, 4 seconds of
271                                            vibration. */
272 
273         bool shouldAutoCancel = true; /**< Optional: If true, the notification will be automatically cancelled when a user clicks it in the panel. */
274 
275         bool localOnly = true;  /**< Optional: whether or not the notification should bridge to other devices.
276                                                Available from Android API 20 or above. */
277 
278         bool ongoing = false;   /**< Optional: If true, then it cannot be dismissed by the user and it must be dismissed manually.
279                                      Typically used for ongoing background tasks that the user is actively engaged with. To
280                                      dismiss such notification, you need to call removeDeliveredNotification() or
281                                      removeAllDeliveredNotifications(). */
282 
283         bool alertOnlyOnce = false; /**< Optional: Set this flag if you would only like the sound, vibrate and ticker to be played if the notification
284                                          is not already showing. */
285 
286         /** Controls timestamp visibility and format. */
287         enum TimestampVisibility
288         {
289             off,                    /**< Do not show timestamp. */
290             normal,                 /**< Show normal timestamp. */
291             chronometer,            /**< Show chronometer as a stopwatch. Available from Android API 16 or above. */
292             countDownChronometer    /**< Set the chronometer to count down instead of counting up. Available from Android API 24 or above.*/
293         };
294 
295         TimestampVisibility timestampVisibility = normal;  /**< Optional. */
296 
297         /** Controls badge icon type to use if a notification is shown as a badge. Available from Android API 26 or above. */
298         enum BadgeIconType
299         {
300             none,
301             small,
302             large
303         };
304 
305         BadgeIconType badgeIconType = large;
306 
307         /** Controls sound and vibration behaviour for group notifications. Available from Android API 26 or above. */
308         enum GroupAlertBehaviour
309         {
310             alertAll,           /**< both child notifications and group notifications should produce sound and vibration. */
311             AlertSummary,       /**< all child notifications in the group should have no sound nor vibration, even
312                                      if corresponding notification channel has sounds and vibrations enabled. */
313             AlertChildren       /**< summary notifications in the group should have no sound nor vibration, even if
314                                      corresponding notification channel has sounds and vibrations enabled. */
315         };
316 
317         GroupAlertBehaviour groupAlertBehaviour = alertAll;
318 
319         int timeoutAfterMs = 0;    /**< specifies a duration in milliseconds, after which the notification should be
320                                         cancelled, if it is not already canceled. Available from Android API 26 or above. */
321         /**@}*/
322     };
323 
324 
325     //==============================================================================
326     /** Describes settings we want to use for current device. Note that at the
327         moment this is only used on iOS and partially on OSX.
328 
329         On OSX only allow* flags are used and they control remote notifications only.
330         To control sound, alert and badge settings for local notifications on OSX,
331         use Notifications settings in System Preferences.
332 
333         To setup push notifications for current device, provide permissions required,
334         as well as register categories of notifications you want to support. Each
335         category needs to have a unique identifier and it can optionally have multiple
336         actions. Each action also needs to have a unique identifier. The example setup
337         may look as follows:
338 
339         @code
340 
341         using Action   = PushNotifications::Settings::Action;
342         using Category = PushNotifications::Settings::Category;
343 
344         Action okAction;
345         okAction.identifier = "okAction";
346         okAction.title = "OK!";
347         okAction.style = Action::button;
348         okAction.triggerInBackground = true;
349 
350         Action cancelAction;
351         cancelAction.identifier = "cancelAction";
352         cancelAction.title = "Cancel";
353         cancelAction.style = Action::button;
354         cancelAction.triggerInBackground = true;
355         cancelAction.destructive = true;
356 
357         Action textAction;
358         textAction.identifier = "textAction";
359         textAction.title = "Enter text";
360         textAction.style = Action::text;
361         textAction.triggerInBackground = true;
362         textAction.destructive = false;
363         textAction.textInputButtonText = "Ok";
364         textAction.textInputPlaceholder = "Enter text...";
365 
366         Category okCategory;
367         okCategory.identifier = "okCategory";
368         okCategory.actions = { okAction };
369 
370         Category okCancelCategory;
371         okCancelCategory.identifier = "okCancelCategory";
372         okCancelCategory.actions = { okAction, cancelAction };
373 
374         Category textCategory;
375         textCategory.identifier = "textCategory";
376         textCategory.actions = { textAction };
377         textCategory.sendDismissAction = true;
378 
379         PushNotifications::Settings settings;
380         settings.allowAlert = true;
381         settings.allowBadge = true;
382         settings.allowSound = true;
383         settings.categories = { okCategory, okCancelCategory, textCategory };
384 
385         @endcode
386     */
387     struct Settings
388     {
389         using Action = Notification::Action;
390 
391         /** Describes a category of a notification. Each category has a unique identifier
392             and a list of associated actions.
393             Note that the OS may allow only a limited number of actions to be presented, so
394             always present most important actions first.
395         */
396         struct Category
397         {
398             juce::String identifier;         /**< unique identifier */
399             juce::Array<Action> actions;     /**< optional list of actions within this category */
400             bool sendDismissAction = false;  /**< whether dismiss action will be sent to the app (from iOS 10 only) */
401         };
402 
403         bool allowSound = false;      /**< whether the app should play a sound upon notification */
404         bool allowAlert = false;      /**< whether the app should present an alert upon notification */
405         bool allowBadge = false;      /**< whether the app may badge its icon upon notification */
406         Array<Category> categories;   /**< list of categories the app wants to support */
407     };
408 
409     /** Initialises push notifications on current device with the settings provided.
410         Call this on your application startup and on iOS the first time the application starts,
411         a user will be presented with a permission request dialog to give push notifications permission.
412         Once a user responds, Listener::notificationSettingsReceived() will be called so that
413         you can check what permissions where actually granted. The listener callback will be called
414         on each subsequent startup too (provided you called requestPermissionsWithSettings() on previous
415         application run). This way you can check what are current push notifications permissions.
416 
417         Note that settings are currently only used on iOS. When calling on other platforms, Settings
418         with no categories and all allow* flags set to true will be received in
419         Listener::notificationSettingsReceived().
420 
421         You can also call requestSettingsUsed() to explicitly ask for current settings.
422     */
423     void requestPermissionsWithSettings (const Settings& settings);
424 
425     /** Sends an asynchronous request to retrieve current settings that are currently in use.
426         These can be exactly the same as used in requestPermissionsWithSettings(), but depending
427         on user's subsequent changes in OS settings, the actual current settings may be
428         different (e.g. user might have later decided to disable sounds).
429 
430         Note that settings are currently only used on iOS and partially on OSX.
431 
432         On OSX, only allow* flags are used and they refer to remote notifications only. For
433         local notifications, refer to System Preferences.
434 
435         When calling this function on other platforms, Settings with no categories and all allow*
436         flags set to true will be received in Listener::notificationSettingsReceived().
437     */
438     void requestSettingsUsed();
439 
440     //==============================================================================
441     /** Android API level 26 or higher only: Represents notification channel through which
442         notifications will be sent. Starting from Android API level 26, you should call setupChannels()
443         at the start of your application, before posting any notifications. Then, when sending notifications,
444         assign a channel to each created notification.
445     */
446     struct Channel
447     {
448         String identifier;          /**< Required: Unique channel identifier. */
449         String name;                /**< Required: User facing name of the channel. */
450 
451         /** Controls how interruptive the notification posted on this channel are. */
452         enum Importance
453         {
454             none,
455             min,
456             low,
457             normal,
458             high,
459             max
460         };
461 
462         Importance importance = normal;     /**< Required. */
463         Notification::LockScreenAppearance lockScreenAppearance = Notification::showPartially;  /**< Optional. */
464 
465         String description;                 /**< Optional: user visible description of the channel. */
466         String groupId;                     /**< Required: group this channel belongs to (see ChannelGroup). */
467         Colour ledColour;                   /**< Optional: sets the led colour for notifications in this channel. */
468         bool bypassDoNotDisturb = false;    /**< Optional: true if notifications in this channel can bypass do not disturb setting. */
469         bool canShowBadge = false;          /**< Optional: true if notifications in this channel can show badges in a Launcher application. */
470         bool enableLights = false;          /**< Optional: true if notifications in this channel should show lights (subject to hardware support). */
471         bool enableVibration = false;       /**< Optional: true if notifications in this channel should trigger vibrations. */
472 
473         URL soundToPlay;                    /**< Optional: sound to play in this channel. See Notification::soundToPlay for more info. */
474         Array<int> vibrationPattern;        /**< Optional: vibration pattern for this channel. See Notification::vibrationPattern for more info. */
475     };
476 
477     /** Android API level 26 or higher only: represents a channel group. This allows for
478         visual grouping of corresponding channels in notification settings presented to the user.
479         At least one channel group has to be specified before notifications can be sent.
480     */
481     struct ChannelGroup
482     {
483         String identifier;                  /**< Required: Unique channel group identifier. */
484         String name;                        /**< Required: User visible name of the channel group. */
485     };
486 
487     /** Android API level 26 or higher only: configures notification channel groups and channels to be
488         used in the app. These have to be setup before notifications can be sent on Android API
489         level 26 or higher.
490     */
491     void setupChannels (const Array<ChannelGroup>& groups, const Array<Channel>& channels);
492 
493     //==============================================================================
494     /** iOS only: sends an asynchronous request to retrieve a list of notifications that were
495         scheduled and not yet delivered.
496 
497         When the list is retrieved, Listener::pendingLocalNotificationsListReceived() will be called.
498     */
499     void getPendingLocalNotifications() const;
500 
501     /** Unschedules a pending local notification with a given identifier. Available from iOS 10. */
502     void removePendingLocalNotification (const String& identifier);
503 
504     /** Unschedules all pending local notifications. iOS only. */
505     void removeAllPendingLocalNotifications();
506 
507     //==============================================================================
508     /** Checks whether notifications are enabled for given application.
509         On iOS and OSX this will always return true, use requestSettingsUsed() instead.
510     */
511     bool areNotificationsEnabled() const;
512 
513     /** On iOS as well as on Android, sends a local notification.
514         On Android and iOS 10 or above, this will refresh an existing notification
515         if the same identifier is used as in a notification that was already sent
516         and not yet responded by a user.
517     */
518     void sendLocalNotification (const Notification& notification);
519 
520     /** Sends a request for a list of notifications delivered. Such notifications are visible in the
521         notification area on the device and they are still waiting for user action/response.
522         When the request is finished Listener::deliveredNotificationsListReceived() will be called.
523 
524         On iOS, iOS version 10 or higher is required. On Android, API level 18 or higher is required.
525         For unsupported platforms, Listener::deliveredNotificationsListReceived() will return an empty array.
526     */
527     void getDeliveredNotifications() const;
528 
529     /** Removes a previously delivered notification. This can be useful for instance when the
530         information in the notification becomes obsolete.
531     */
532     void removeDeliveredNotification (const String& identifier);
533 
534     /** Removes all notifications that were delivered. */
535     void removeAllDeliveredNotifications();
536 
537     //==============================================================================
538     /** Retrieves current device token. Note, it is not a good idea to cache this token
539         because it may change in the meantime. Always call this method to get the current
540         token value.
541     */
542     String getDeviceToken() const;
543 
544     /** Android only: allows to subscribe to messages from a specific topic.
545         So you could for instance subscribe this device to all "sports" topic messages
546         to receive any remote notifications that have "sports" topic set.
547         Refer to Firebase documentation for how to send topic messages.
548     */
549     void subscribeToTopic (const String& topic);
550 
551     /** Android only: allows to remove a topic subscription that was previously added with
552         subscribeToTopic().
553     */
554     void unsubscribeFromTopic (const String& topic);
555 
556     /** Android only: sends an upstream message to your app server. The server must implement
557         XMPP Connection Server protocol (refer to Firebase documentation).
558 
559         @param serverSenderId       Represents the sender. Consult your Firebase project
560                                     settings to retrieve the sender id.
561 
562         @param collapseKey          Remote messages with the same collapse key that were not
563                                     yet delivered will be collapsed into one, with the
564                                     newest message replacing all the previous ones.
565                                     Note that there may be a limit of maximum collapse keys
566                                     used at the same time and beyond the limit (refer to
567                                     Firebase documentation) it is not guaranteed which keys
568                                     will be in use by the server.
569 
570         @param messageId            A unique message ID. Used in error callbacks and debugging.
571 
572         @param messageType          Message type.
573 
574         @param timeToLive           TTL in seconds. If 0, the message sending will be attempted
575                                     immediately and it will be dropped if the device is not
576                                     connected. Otherwise, the message will be queued for the
577                                     period specified.
578 
579         @param additionalData       Collection of key-value pairs to be used as an additional
580                                     data for the message.
581     */
582     void sendUpstreamMessage (const String& serverSenderId,
583                               const String& collapseKey,
584                               const String& messageId,
585                               const String& messageType,
586                               int timeToLive,
587                               const StringPairArray& additionalData);
588 
589     //==============================================================================
590     /** Register a listener (ideally on application startup) to receive information about
591         notifications received and any callbacks to async functions called.
592     */
593     struct Listener
594     {
595         virtual ~Listener() = default;
596 
597         /** This callback will be called after you call requestSettingsUsed() or
598             requestPermissionsWithSettings().
599 
600             Note that settings are currently only used on iOS. When called on other platforms, Settings
601             with no categories and all allow flags set to true will be received in
602             Listener::notificationSettingsReceived().
603         */
notificationSettingsReceivedListener604         virtual void notificationSettingsReceived (const Settings& settings) { ignoreUnused (settings); }
605 
606         /** Called when the list of pending notifications, requested by calling
607             getPendingLocalNotifications() is returned. iOS 10 or above only.
608         */
pendingLocalNotificationsListReceivedListener609         virtual void pendingLocalNotificationsListReceived (const Array<Notification>& notifications) { ignoreUnused (notifications); }
610 
611         /** This can be called in multiple different situations, depending on the OS and the situation.
612 
613             On pre iOS 10 device it will be called when a user presses on a notification or when a
614             notification was received when the app was in the foreground already. On iOS 10 it will be
615             called when a user presses on a notification
616 
617             Note: On Android, if remote notification was received while the app was in the background and
618             then user pressed on it, the notification object received in this callback will contain only
619             "properties" member set. Hence, if you want to know what was the notification title, content
620             etc, you need to set them as additional properties, so that you will be able to restore them
621             from "properties" dictionary.
622 
623             Note you can receive this callback on startup, if the application was launched from a notification.
624         */
handleNotificationListener625         virtual void handleNotification (bool isLocalNotification, const Notification& notification) { ignoreUnused (isLocalNotification); ignoreUnused (notification); }
626 
627         /** This can be called when a user performs some action on the notification such as
628             pressing on an action button or responding with a text input.
629             Note that pressing on a notification area, i.e. not on an action button is not considered
630             to be an action, and hence receivedNotification() will be called in that case.
631 
632             Note you can receive this callback on startup, if the application was launched from a notification's action.
633 
634             @param isLocalNotification If the notification is local
635             @param notification        The notification
636             @param actionIdentifier    A String identifying the action
637             @param optionalResponse    Text response a user inputs for notifications with a text input.
638                                        Empty for notifications without a text input option.
639 
640         */
handleNotificationActionListener641         virtual void handleNotificationAction (bool isLocalNotification,
642                                                const Notification& notification,
643                                                const String& actionIdentifier,
644                                                const String& optionalResponse)
645         {
646             ignoreUnused (isLocalNotification);
647             ignoreUnused (notification);
648             ignoreUnused (actionIdentifier);
649             ignoreUnused (optionalResponse);
650         }
651 
652         /** For iOS10 and Android, this can be also called when a user dismissed the notification before
653             responding to it.
654         */
localNotificationDismissedByUserListener655         virtual void localNotificationDismissedByUser (const Notification& notification) { ignoreUnused (notification); }
656 
657         /** Called after getDeliveredNotifications() request is fulfilled. Returns notifications
658             that are visible in the notification area on the device and that are still waiting
659             for a user action/response.
660 
661             On iOS, iOS version 10 or higher is required. On Android, API level 18 or higher is required.
662             For unsupported platforms, an empty array will be returned.
663          */
deliveredNotificationsListReceivedListener664         virtual void deliveredNotificationsListReceived (const Array<Notification>& notifications) { ignoreUnused (notifications); }
665 
666         /** Called whenever a token gets refreshed. You should monitor any token updates, because
667             only the last token that is assigned to device is valid and can be used.
668         */
deviceTokenRefreshedListener669         virtual void deviceTokenRefreshed (const String& token) { ignoreUnused (token); }
670 
671         /** Called when Firebase Cloud Messaging server deletes pending messages. This can happen when
672             1) too many messages were sent to the server (hint: use collapsible messages).
673             2) the devices hasn't been online in a long time (refer to Firebase documentation for
674                the maximum time a message can be stored on FCM before expiring).
675         */
remoteNotificationsDeletedListener676         virtual void remoteNotificationsDeleted() {}
677 
678         /** Called when an upstream message sent with PushNotifications::sendUpstreamMessage() has been
679             sent successfully.
680             Bear in mind that in may take several minutes or more to receive this callback.
681         */
upstreamMessageSentListener682         virtual void upstreamMessageSent (const String& messageId) { ignoreUnused (messageId); }
683 
684         /** Called when there was an error sending an upstream message with
685             PushNotifications::sendUpstreamMessage().
686             Bear in mind that in may take several minutes or more to receive this callback.
687         */
upstreamMessageSendingErrorListener688         virtual void upstreamMessageSendingError (const String& messageId, const String& error) {  ignoreUnused (messageId); ignoreUnused (error); }
689     };
690 
691     void addListener (Listener* l);
692     void removeListener (Listener* l);
693 
694 private:
695     PushNotifications();
696     ~PushNotifications() override;
697 
698     ListenerList<PushNotifications::Listener> listeners;
699 
700    #if JUCE_ANDROID
701     friend bool juce_handleNotificationIntent (void*);
702 
703     friend struct JuceFirebaseInstanceIdService;
704     friend struct JuceFirebaseMessagingService;
705    #endif
706 
707   #if JUCE_PUSH_NOTIFICATIONS
708     struct Pimpl;
709     friend struct Pimpl;
710 
711     std::unique_ptr<Pimpl> pimpl;
712   #endif
713 };
714 
715 } // namespace juce
716