Skip to content

Commit 3288829

Browse files
committed
feature: [IOS] notification service extension not working
1 parent 24fac26 commit 3288829

File tree

6 files changed

+156
-4
lines changed

6 files changed

+156
-4
lines changed

example/.flutter-plugins-dependencies

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"onesignal_flutter","path":"/Users/efraespada/landa-workspace/OneSignal-Flutter-SDK/","dependencies":[]}],"android":[{"name":"onesignal_flutter","path":"/Users/efraespada/landa-workspace/OneSignal-Flutter-SDK/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"onesignal_flutter","dependencies":[]}],"date_created":"2021-08-12 01:52:39.082971","version":"2.2.3"}
1+
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"onesignal_flutter","path":"/Users/efraespada/landa-workspace/OneSignal-Flutter-SDK/","dependencies":[]}],"android":[{"name":"onesignal_flutter","path":"/Users/efraespada/landa-workspace/OneSignal-Flutter-SDK/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"onesignal_flutter","dependencies":[]}],"date_created":"2021-08-13 17:25:40.930142","version":"2.2.3"}

ios/Classes/OneSignalPlugin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
@interface OneSignalPlugin : NSObject<FlutterPlugin, OSSubscriptionObserver, OSPermissionObserver, OSEmailSubscriptionObserver, OSSMSSubscriptionObserver>
3232

33+
@property (strong, nonatomic) FlutterMethodChannel *callbackChannel;
34+
3335
// Do NOT initialize instances of this class.
3436
// You must only reference the shared instance.
3537
+ (instancetype)sharedInstance;

ios/Classes/OneSignalPlugin.m

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
*/
2727

2828
#import "OneSignalPlugin.h"
29+
#import "XOneSignalNotificationService.h"
2930
#import "OSFlutterCategories.h"
3031
#import "OSFlutterTagsController.h"
3132
#import "OSFlutterInAppMessagesController.h"
@@ -35,6 +36,8 @@ @interface OneSignalPlugin ()
3536

3637
@property (strong, nonatomic) FlutterMethodChannel *channel;
3738

39+
@property (strong, nonatomic) FlutterEngine *headlessRunner;
40+
@property (strong, nonatomic) NSObject<FlutterPluginRegistrar> *registrar;
3841
/*
3942
Will be true if the SDK is waiting for the
4043
user's consent before initializing.
@@ -56,6 +59,8 @@ it will add the observers (ie. subscription)
5659
@property (strong, nonatomic) NSMutableDictionary* notificationCompletionCache;
5760
@property (strong, nonatomic) NSMutableDictionary* receivedNotificationCache;
5861

62+
@property (strong, nonatomic) NSUserDefaults *persistentState;
63+
5964
@end
6065

6166
@implementation OneSignalPlugin
@@ -74,6 +79,9 @@ + (instancetype)sharedInstance {
7479
return sharedInstance;
7580
}
7681

82+
static FlutterPluginRegistrantCallback registerPlugins = nil;
83+
static BOOL backgroundIsolateRun = NO;
84+
7785
#pragma mark FlutterPlugin
7886
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
7987

@@ -88,13 +96,36 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
8896
methodChannelWithName:@"OneSignal"
8997
binaryMessenger:[registrar messenger]];
9098

99+
OneSignalPlugin.sharedInstance.registrar = registrar;
100+
OneSignalPlugin.sharedInstance.headlessRunner = [[FlutterEngine alloc]
101+
initWithName:@"OneSignalHeadlessRunner"
102+
project:nil
103+
allowHeadlessExecution:YES];
104+
105+
OneSignalPlugin.sharedInstance.persistentState = [NSUserDefaults standardUserDefaults];
106+
107+
108+
OneSignalPlugin.sharedInstance.callbackChannel =
109+
[FlutterMethodChannel methodChannelWithName:@"OneSignalBackground"
110+
binaryMessenger:OneSignalPlugin.sharedInstance.headlessRunner.binaryMessenger];
111+
91112
[registrar addMethodCallDelegate:OneSignalPlugin.sharedInstance channel:OneSignalPlugin.sharedInstance.channel];
113+
// [registrar addMethodCallDelegate:OneSignalPlugin.sharedInstance channel:OneSignalPlugin.sharedInstance.callbackChannel];
92114

93115
[OSFlutterTagsController registerWithRegistrar:registrar];
94116
[OSFlutterInAppMessagesController registerWithRegistrar:registrar];
95117
[OSFlutterOutcomeEventsController registerWithRegistrar:registrar];
96118
}
97119

120+
+ (void)setPluginRegistrantCallback:(FlutterPluginRegistrantCallback)callback {
121+
registerPlugins = callback;
122+
}
123+
124+
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
125+
[self initNotificationWillShowHandlerParamsById:[self getCallbackDispatcherHandle] withNotification: [self getCallbackNotificationHandle]];
126+
return YES;
127+
}
128+
98129
- (void)addObservers {
99130
[OneSignal addSubscriptionObserver:self];
100131
[OneSignal addPermissionObserver:self];
@@ -150,8 +181,12 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
150181
[self initInAppMessageClickedHandlerParams];
151182
else if ([@"OneSignal#initNotificationWillShowInForegroundHandlerParams" isEqualToString:call.method])
152183
[self initNotificationWillShowInForegroundHandlerParams];
184+
else if ([@"OneSignal#initNotificationWillShowHandlerParams" isEqualToString:call.method])
185+
[self initNotificationWillShowHandlerParams:call withResult:result];
153186
else if ([@"OneSignal#completeNotification" isEqualToString:call.method])
154187
[self completeNotification:call withResult:result];
188+
else if ([@"OneSignal#backgroundHandlerInitialized" isEqualToString:call.method])
189+
NSLog(@"Background channel ready");
155190
else
156191
result(FlutterMethodNotImplemented);
157192
}
@@ -350,6 +385,65 @@ - (void)initNotificationWillShowInForegroundHandlerParams {
350385
self.hasSetNotificationWillShowInForegroundHandler = YES;
351386
}
352387

388+
- (int64_t)getCallbackDispatcherHandle {
389+
id handle = [OneSignalPlugin.sharedInstance.persistentState objectForKey:@"callback_dispatcher_handle"];
390+
if (handle == nil) {
391+
return 0;
392+
}
393+
return [handle longLongValue];
394+
}
395+
396+
- (void)setCallbackDispatcherHandle:(int64_t)handle {
397+
[OneSignalPlugin.sharedInstance.persistentState setObject:[NSNumber numberWithLongLong:handle]
398+
forKey:@"callback_dispatcher_handle"];
399+
}
400+
401+
- (int64_t)getCallbackNotificationHandle {
402+
id handle = [OneSignalPlugin.sharedInstance.persistentState objectForKey:@"callback_notification_handle"];
403+
if (handle == nil) {
404+
return 0;
405+
}
406+
return [handle longLongValue];
407+
}
408+
409+
- (void)setCallbackNotificationHandle:(int64_t)handle {
410+
[OneSignalPlugin.sharedInstance.persistentState setObject:[NSNumber numberWithLongLong:handle]
411+
forKey:@"callback_notification_handle"];
412+
}
413+
414+
- (void)initNotificationWillShowHandlerParams:(FlutterMethodCall*)call withResult:(FlutterResult)result {
415+
int64_t pluginCallbackHandle = [call.arguments[@"pluginCallbackHandle"] longValue];
416+
int64_t notificationCallbackHandle = [call.arguments[@"notificationCallbackHandle"] longValue];
417+
[self initNotificationWillShowHandlerParamsById:pluginCallbackHandle withNotification: notificationCallbackHandle];
418+
}
419+
420+
- (void)initNotificationWillShowHandlerParamsById:(int64_t)dispatcherCallbackHandle withNotification: (int64_t)notificationCallbackHandle {
421+
NSLog(@"Initializing Headless Runner");
422+
423+
NSAssert(dispatcherCallbackHandle != 0, @"dispatcherCallbackHandle can't be 0");
424+
NSAssert(notificationCallbackHandle != 0, @"notificationCallbackHandle can't be 0");
425+
426+
[self setCallbackDispatcherHandle:dispatcherCallbackHandle];
427+
[self setCallbackNotificationHandle:notificationCallbackHandle];
428+
429+
FlutterCallbackInformation *info = [FlutterCallbackCache lookupCallbackInformation:dispatcherCallbackHandle];
430+
NSAssert(info != nil, @"failed to find callback");
431+
432+
NSString *entrypoint = info.callbackName;
433+
NSString *uri = info.callbackLibraryPath;
434+
[OneSignalPlugin.sharedInstance.headlessRunner runWithEntrypoint:entrypoint libraryURI:uri];
435+
436+
// Once our headless runner has been started, we need to register the application's plugins
437+
// with the runner in order for them to work on the background isolate. `registerPlugins` is
438+
// a callback set from AppDelegate.m in the main application. This callback should register
439+
// all relevant plugins (excluding those which require UI).
440+
[OneSignalPlugin.sharedInstance.registrar addMethodCallDelegate:self channel:OneSignalPlugin.sharedInstance.callbackChannel];
441+
if (!backgroundIsolateRun && registerPlugins != nil) {
442+
registerPlugins(OneSignalPlugin.sharedInstance.headlessRunner);
443+
}
444+
backgroundIsolateRun = YES;
445+
}
446+
353447
#pragma mark Opened Notification Handlers
354448
- (void)handleNotificationOpened:(OSNotificationOpenedResult *)result {
355449
[self.channel invokeMethod:@"OneSignal#handleOpenedNotification" arguments:result.toJson];
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// NotificationService.h
3+
// OneSignalNotificationServiceExtension
4+
//
5+
// Created by Brad Hesse on 7/13/18.
6+
// Copyright © 2018 The Chromium Authors. All rights reserved.
7+
//
8+
9+
#import <UserNotifications/UserNotifications.h>
10+
11+
@interface XOneSignalNotificationService : UNNotificationServiceExtension
12+
13+
@end
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//
2+
// NotificationService.m
3+
// OneSignalNotificationServiceExtension
4+
//
5+
// Created by Brad Hesse on 7/13/18.
6+
// Copyright © 2018 The Chromium Authors. All rights reserved.
7+
//
8+
9+
#import <OneSignal/OneSignal.h>
10+
#import "OneSignalPlugin.h"
11+
12+
#import "XOneSignalNotificationService.h"
13+
14+
static XOneSignalNotificationService *obj;
15+
16+
@interface XOneSignalNotificationService ()
17+
18+
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
19+
@property (nonatomic, strong) UNNotificationRequest *receivedRequest;
20+
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
21+
22+
@end
23+
24+
@implementation XOneSignalNotificationService
25+
26+
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
27+
self.receivedRequest = request;
28+
self.contentHandler = contentHandler;
29+
self.bestAttemptContent = [request.content mutableCopy];
30+
NSLog(@"didReceiveNotificationRequest");
31+
[OneSignalPlugin.sharedInstance.callbackChannel invokeMethod: @"OneSignal#onBackgroundNotification" arguments: self.bestAttemptContent];
32+
33+
// [OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent withContentHandler:self.contentHandler];
34+
}
35+
36+
- (void)serviceExtensionTimeWillExpire {
37+
// Called just before the extension will be terminated by the system.
38+
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
39+
40+
[OneSignal serviceExtensionTimeWillExpireRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent];
41+
42+
self.contentHandler(self.bestAttemptContent);
43+
}
44+
45+
@end

lib/onesignal_flutter.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ void _callbackDispatcher() {
7070
}
7171
});
7272

73-
// Once we've finished initializing, let the native portion of the plugin
74-
// know that it can start scheduling alarms.
73+
print("OneSignalPlugin - plugin callback ready");
7574
_channel.invokeMethod<void>('OneSignal#backgroundHandlerInitialized');
7675
}
7776

@@ -176,7 +175,6 @@ class OneSignal {
176175
NotificationWillShowInForegroundHandler handler) {
177176
if (Platform.isIOS) {
178177
setNotificationWillShowInForegroundHandler(handler);
179-
return;
180178
}
181179
final CallbackHandle bgHandle =
182180
PluginUtilities.getCallbackHandle(_callbackDispatcher)!;

0 commit comments

Comments
 (0)