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