Skip to content

Commit 34da46d

Browse files
committed
[APN] Added badge number. Added single services container for user notifications.
1 parent a6807fe commit 34da46d

File tree

8 files changed

+184
-6
lines changed

8 files changed

+184
-6
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## 2021-02-05
6+
7+
## Added
8+
9+
- `badge_number` property, `set_badge_number`, `get_badge_number` methods to `PushNotifications` plugin.
10+
- `GodotUserNotificationDelegate` and `UserNotificationService` can be used by as a single interface to process incoming notifications (both remote and local).
11+
512
## 2021-02-03
613

714
## Added

plugins/apn/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,19 @@ func _ready():
2222

2323
## Enum
2424

25-
Type: `PushOptions`
26-
Values: `PUSH_ALERT`, `PUSH_BADGE`, `PUSH_SOUND`
25+
Type: `PushOptions`
26+
Values: `PUSH_ALERT`, `PUSH_BADGE`, `PUSH_SOUND`, `PUSH_SETTINGS`
2727

2828
## Methods
2929

3030
`register_push_notifications(PushOptions options)` - Registers device to receive remote notifications through Apple Push Notification service.
31+
`set_badge_number(int value)` - Sets the badge value of the app icon on the Home screen.
32+
`get_badge_number()` - Returns the badge value of the app icon on the Home screen.
3133

3234
## Properties
3335

36+
`badge_number: int` - The number represents the badge of the app icon on the Home screen.
37+
3438
## Signals
3539

3640
`device_address_changed(String token)` - Called whenever iOS device updates remote notification token value.

plugins/apn/apn.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,17 @@ class APNPlugin : public Object {
4343
PUSH_ALERT = 1 << 0,
4444
PUSH_BADGE = 1 << 1,
4545
PUSH_SOUND = 1 << 2,
46+
PUSH_SETTINGS = 1 << 3,
4647
};
4748

4849
static APNPlugin *get_singleton();
4950

5051
void register_push_notifications(PushOptions options);
5152
void update_device_token(String token);
5253

54+
void set_badge_number(int value);
55+
int get_badge_number();
56+
5357
APNPlugin();
5458
~APNPlugin();
5559
};

plugins/apn/apn.mm

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
#include "core/class_db.h"
3636
#include "core/project_settings.h"
3737

38-
#import "apn_implementation.h"
38+
#import "godot_apn_delegate.h"
3939

4040
static APNPlugin *singleton;
4141

@@ -46,11 +46,16 @@
4646
void APNPlugin::_bind_methods() {
4747
ClassDB::bind_method(D_METHOD("register_push_notifications", "options"), &APNPlugin::register_push_notifications);
4848

49+
ClassDB::bind_method(D_METHOD("set_badge_number", "value"), &APNPlugin::set_badge_number);
50+
ClassDB::bind_method(D_METHOD("get_badge_number"), &APNPlugin::get_badge_number);
51+
ADD_PROPERTY(PropertyInfo(Variant::INT, "badge_number"), "set_badge_number", "get_badge_number");
52+
4953
ADD_SIGNAL(MethodInfo("device_address_changed", PropertyInfo(Variant::STRING, "id")));
5054

5155
BIND_ENUM_CONSTANT(PUSH_ALERT);
5256
BIND_ENUM_CONSTANT(PUSH_BADGE);
5357
BIND_ENUM_CONSTANT(PUSH_SOUND);
58+
BIND_ENUM_CONSTANT(PUSH_SETTINGS);
5459
}
5560

5661
void APNPlugin::register_push_notifications(PushOptions options) {
@@ -75,6 +80,14 @@
7580
emit_signal("device_address_changed", token);
7681
}
7782

83+
void APNPlugin::set_badge_number(int value) {
84+
UIApplication.sharedApplication.applicationIconBadgeNumber = (long)value;
85+
}
86+
87+
int APNPlugin::get_badge_number() {
88+
return (int)UIApplication.sharedApplication.applicationIconBadgeNumber;
89+
}
90+
7891
APNPlugin::APNPlugin() {
7992
singleton = this;
8093
}

plugins/apn/apn_implementation.h renamed to plugins/apn/godot_apn_delegate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*************************************************************************/
2-
/* apn_implementation.h */
2+
/* godot_apn_delegate.h */
33
/*************************************************************************/
44
/* This file is part of: */
55
/* GODOT ENGINE */

plugins/apn/apn_implementation.mm renamed to plugins/apn/godot_apn_delegate.mm

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*************************************************************************/
2-
/* apn_implementation.mm */
2+
/* godot_apn_delegate.mm */
33
/*************************************************************************/
44
/* This file is part of: */
55
/* GODOT ENGINE */
@@ -28,10 +28,11 @@
2828
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
2929
/*************************************************************************/
3030

31-
#import "apn_implementation.h"
31+
#import "godot_apn_delegate.h"
3232

3333
#include "apn.h"
3434

35+
#import "godot_user_notification_delegate.h"
3536
#import "platform/iphone/godot_app_delegate.h"
3637

3738
struct APNSInitializer {
@@ -51,6 +52,10 @@ @implementation GodotAPNAppDelegate
5152
- (instancetype)init {
5253
self = [super init];
5354

55+
if (self) {
56+
UNUserNotificationCenter.currentNotificationCenter.delegate = [GodotUserNotificationDelegate shared];
57+
}
58+
5459
return self;
5560
}
5661

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*************************************************************************/
2+
/* godot_user_notification_delegate.h */
3+
/*************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/*************************************************************************/
8+
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
9+
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/*************************************************************************/
30+
31+
#import <UserNotifications/UserNotifications.h>
32+
33+
typedef NSObject<UNUserNotificationCenterDelegate> UserNotificationService;
34+
35+
@interface GodotUserNotificationDelegate : NSObject <UNUserNotificationCenterDelegate>
36+
37+
@property(class, readonly, strong) NSArray<UserNotificationService *> *services;
38+
39+
+ (instancetype)shared;
40+
41+
+ (void)addService:(UserNotificationService *)service;
42+
43+
@end
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*************************************************************************/
2+
/* godot_user_notification_delegate.m */
3+
/*************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/*************************************************************************/
8+
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
9+
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/*************************************************************************/
30+
31+
#import "godot_user_notification_delegate.h"
32+
33+
@interface GodotUserNotificationDelegate ()
34+
35+
@end
36+
37+
@implementation GodotUserNotificationDelegate
38+
39+
static NSMutableArray<UserNotificationService *> *services = nil;
40+
41+
+ (NSArray<UserNotificationService *> *)services {
42+
return services;
43+
}
44+
45+
+ (void)load {
46+
services = [NSMutableArray new];
47+
}
48+
49+
+ (instancetype)shared {
50+
static GodotUserNotificationDelegate *sharedInstance = nil;
51+
static dispatch_once_t onceToken;
52+
dispatch_once(&onceToken, ^{
53+
sharedInstance = [[GodotUserNotificationDelegate alloc] init];
54+
});
55+
return sharedInstance;
56+
}
57+
58+
+ (void)addService:(UserNotificationService *)service {
59+
if (!services || !service) {
60+
return;
61+
}
62+
[services addObject:service];
63+
}
64+
65+
// MARK: Delegate
66+
67+
// The method will be called on the delegate only if the application is in the foreground. If the method is not implemented or the handler is not called in a timely manner then the notification will not be presented. The application can choose to have the notification presented as a sound, badge, alert and/or in the notification list. This decision should be based on whether the information in the notification is otherwise visible to the user.
68+
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
69+
for (UserNotificationService *service in services) {
70+
if (![service respondsToSelector:_cmd]) {
71+
continue;
72+
}
73+
74+
[service userNotificationCenter:center willPresentNotification:notification withCompletionHandler:completionHandler];
75+
}
76+
}
77+
78+
// The method will be called on the delegate when the user responded to the notification by opening the application, dismissing the notification or choosing a UNNotificationAction. The delegate must be set before the application returns from application:didFinishLaunchingWithOptions:.
79+
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
80+
for (UserNotificationService *service in services) {
81+
if (![service respondsToSelector:_cmd]) {
82+
continue;
83+
}
84+
85+
[service userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
86+
}
87+
}
88+
89+
// The method will be called on the delegate when the application is launched in response to the user's request to view in-app notification settings.
90+
// Add UNAuthorizationOptionProvidesAppNotificationSettings as an option in requestAuthorizationWithOptions:completionHandler: to add a button to inline notification settings view and the notification settings view in Settings.
91+
// The notification will be nil when opened from Settings.
92+
- (void)userNotificationCenter:(UNUserNotificationCenter *)center openSettingsForNotification:(nullable UNNotification *)notification __API_AVAILABLE(macos(10.14), ios(12.0))__API_UNAVAILABLE(watchos, tvos) {
93+
for (UserNotificationService *service in services) {
94+
if (![service respondsToSelector:_cmd]) {
95+
continue;
96+
}
97+
98+
[service userNotificationCenter:center openSettingsForNotification:notification];
99+
}
100+
}
101+
102+
@end

0 commit comments

Comments
 (0)