26
26
*/
27
27
28
28
#import " OneSignalPlugin.h"
29
+ #import " XOneSignalNotificationService.h"
29
30
#import " OSFlutterCategories.h"
30
31
#import " OSFlutterTagsController.h"
31
32
#import " OSFlutterInAppMessagesController.h"
@@ -35,6 +36,8 @@ @interface OneSignalPlugin ()
35
36
36
37
@property (strong , nonatomic ) FlutterMethodChannel *channel;
37
38
39
+ @property (strong , nonatomic ) FlutterEngine *headlessRunner;
40
+ @property (strong , nonatomic ) NSObject <FlutterPluginRegistrar> *registrar;
38
41
/*
39
42
Will be true if the SDK is waiting for the
40
43
user's consent before initializing.
@@ -56,6 +59,8 @@ it will add the observers (ie. subscription)
56
59
@property (strong , nonatomic ) NSMutableDictionary * notificationCompletionCache;
57
60
@property (strong , nonatomic ) NSMutableDictionary * receivedNotificationCache;
58
61
62
+ @property (strong , nonatomic ) NSUserDefaults *persistentState;
63
+
59
64
@end
60
65
61
66
@implementation OneSignalPlugin
@@ -74,6 +79,9 @@ + (instancetype)sharedInstance {
74
79
return sharedInstance;
75
80
}
76
81
82
+ static FlutterPluginRegistrantCallback registerPlugins = nil ;
83
+ static BOOL backgroundIsolateRun = NO ;
84
+
77
85
#pragma mark FlutterPlugin
78
86
+ (void )registerWithRegistrar : (NSObject <FlutterPluginRegistrar>*)registrar {
79
87
@@ -88,13 +96,36 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
88
96
methodChannelWithName: @" OneSignal"
89
97
binaryMessenger: [registrar messenger ]];
90
98
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
+
91
112
[registrar addMethodCallDelegate: OneSignalPlugin.sharedInstance channel: OneSignalPlugin.sharedInstance.channel];
113
+ // [registrar addMethodCallDelegate:OneSignalPlugin.sharedInstance channel:OneSignalPlugin.sharedInstance.callbackChannel];
92
114
93
115
[OSFlutterTagsController registerWithRegistrar: registrar];
94
116
[OSFlutterInAppMessagesController registerWithRegistrar: registrar];
95
117
[OSFlutterOutcomeEventsController registerWithRegistrar: registrar];
96
118
}
97
119
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
+
98
129
- (void )addObservers {
99
130
[OneSignal addSubscriptionObserver: self ];
100
131
[OneSignal addPermissionObserver: self ];
@@ -150,8 +181,12 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
150
181
[self initInAppMessageClickedHandlerParams ];
151
182
else if ([@" OneSignal#initNotificationWillShowInForegroundHandlerParams" isEqualToString: call.method])
152
183
[self initNotificationWillShowInForegroundHandlerParams ];
184
+ else if ([@" OneSignal#initNotificationWillShowHandlerParams" isEqualToString: call.method])
185
+ [self initNotificationWillShowHandlerParams: call withResult: result];
153
186
else if ([@" OneSignal#completeNotification" isEqualToString: call.method])
154
187
[self completeNotification: call withResult: result];
188
+ else if ([@" OneSignal#backgroundHandlerInitialized" isEqualToString: call.method])
189
+ NSLog (@" Background channel ready" );
155
190
else
156
191
result (FlutterMethodNotImplemented);
157
192
}
@@ -350,6 +385,65 @@ - (void)initNotificationWillShowInForegroundHandlerParams {
350
385
self.hasSetNotificationWillShowInForegroundHandler = YES ;
351
386
}
352
387
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
+
353
447
#pragma mark Opened Notification Handlers
354
448
- (void )handleNotificationOpened : (OSNotificationOpenedResult *)result {
355
449
[self .channel invokeMethod: @" OneSignal#handleOpenedNotification" arguments: result.toJson];
0 commit comments