7 #include "flutter/fml/logging.h"
8 #include "flutter/fml/paths.h"
9 #include "flutter/lib/ui/plugins/callback_cache.h"
17 @selector(application:didReceiveRemoteNotification:fetchCompletionHandler:),
18 @selector(application:performFetchWithCompletionHandler:)};
21 - (void)handleDidEnterBackground:(NSNotification*)notification
22 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions");
23 - (void)handleWillEnterForeground:(NSNotification*)notification
24 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions");
25 - (void)handleWillResignActive:(NSNotification*)notification
26 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions");
27 - (void)handleDidBecomeActive:(NSNotification*)notification
28 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions");
29 - (void)handleWillTerminate:(NSNotification*)notification
30 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions");
34 UIBackgroundTaskIdentifier _debugBackgroundTask;
40 - (void)addObserverFor:(NSString*)name selector:(
SEL)selector {
41 [[NSNotificationCenter defaultCenter] addObserver:self selector:selector name:name object:nil];
44 - (instancetype)init {
45 if (
self = [super init]) {
48 #if not APPLICATION_EXTENSION_API_ONLY
49 [
self addObserverFor:UIApplicationDidEnterBackgroundNotification
50 selector:@selector(handleDidEnterBackground:)];
51 [
self addObserverFor:UIApplicationWillEnterForegroundNotification
52 selector:@selector(handleWillEnterForeground:)];
53 [
self addObserverFor:UIApplicationWillResignActiveNotification
54 selector:@selector(handleWillResignActive:)];
55 [
self addObserverFor:UIApplicationDidBecomeActiveNotification
56 selector:@selector(handleDidBecomeActive:)];
57 [
self addObserverFor:UIApplicationWillTerminateNotification
58 selector:@selector(handleWillTerminate:)];
60 _delegates = [NSPointerArray weakObjectsPointerArray];
61 _debugBackgroundTask = UIBackgroundTaskInvalid;
66 static BOOL IsPowerOfTwo(NSUInteger x) {
67 return x != 0 && (x & (x - 1)) == 0;
70 - (BOOL)isSelectorAddedDynamically:(
SEL)selector {
72 if (selector == aSelector) {
79 - (BOOL)hasPluginThatRespondsToSelector:(
SEL)selector {
80 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in [
_delegates allObjects]) {
84 if ([delegate respondsToSelector:selector]) {
92 [_delegates addPointer:(__bridge void*)delegate];
98 - (BOOL)application:(UIApplication*)application
99 didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
100 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in [
_delegates allObjects]) {
104 if ([delegate respondsToSelector:_cmd]) {
105 if (![delegate application:application didFinishLaunchingWithOptions:launchOptions]) {
113 - (BOOL)application:(UIApplication*)application
114 willFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
115 flutter::DartCallbackCache::LoadCacheFromDisk();
116 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in [
_delegates allObjects]) {
120 if ([delegate respondsToSelector:_cmd]) {
121 if (![delegate application:application willFinishLaunchingWithOptions:launchOptions]) {
129 - (void)handleDidEnterBackground:(NSNotification*)notification
130 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions") {
131 UIApplication* application = [UIApplication sharedApplication];
132 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
138 _debugBackgroundTask = [application
139 beginBackgroundTaskWithName:@"Flutter debug task"
141 if (_debugBackgroundTask != UIBackgroundTaskInvalid) {
142 [application endBackgroundTask:_debugBackgroundTask];
143 _debugBackgroundTask = UIBackgroundTaskInvalid;
146 << "\nThe OS has terminated the Flutter debug connection for being "
147 "inactive in the background for too long.\n\n"
148 "There are no errors with your Flutter application.\n\n"
149 "To reconnect, launch your application again via 'flutter run'";
151 #endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
152 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
156 if ([delegate respondsToSelector:
@selector(applicationDidEnterBackground:)]) {
157 [delegate applicationDidEnterBackground:application];
162 - (void)handleWillEnterForeground:(NSNotification*)notification
163 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions") {
164 UIApplication* application = [UIApplication sharedApplication];
165 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
166 if (_debugBackgroundTask != UIBackgroundTaskInvalid) {
167 [application endBackgroundTask:_debugBackgroundTask];
168 _debugBackgroundTask = UIBackgroundTaskInvalid;
170 #endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
171 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
175 if ([delegate respondsToSelector:
@selector(applicationWillEnterForeground:)]) {
176 [delegate applicationWillEnterForeground:application];
181 - (void)handleWillResignActive:(NSNotification*)notification
182 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions") {
183 UIApplication* application = [UIApplication sharedApplication];
184 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
188 if ([delegate respondsToSelector:
@selector(applicationWillResignActive:)]) {
189 [delegate applicationWillResignActive:application];
194 - (void)handleDidBecomeActive:(NSNotification*)notification
195 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions") {
196 UIApplication* application = [UIApplication sharedApplication];
197 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
201 if ([delegate respondsToSelector:
@selector(applicationDidBecomeActive:)]) {
202 [delegate applicationDidBecomeActive:application];
207 - (void)handleWillTerminate:(NSNotification*)notification
208 NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in app extensions") {
209 UIApplication* application = [UIApplication sharedApplication];
210 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
214 if ([delegate respondsToSelector:
@selector(applicationWillTerminate:)]) {
215 [delegate applicationWillTerminate:application];
220 #pragma GCC diagnostic push
221 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
222 - (void)application:(UIApplication*)application
223 didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings {
224 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
228 if ([delegate respondsToSelector:_cmd]) {
229 [delegate application:application didRegisterUserNotificationSettings:notificationSettings];
233 #pragma GCC diagnostic pop
235 - (void)application:(UIApplication*)application
236 didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
237 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
241 if ([delegate respondsToSelector:_cmd]) {
242 [delegate application:application
243 didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
248 - (void)application:(UIApplication*)application
249 didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
250 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
254 if ([delegate respondsToSelector:_cmd]) {
255 [delegate application:application didFailToRegisterForRemoteNotificationsWithError:error];
260 - (void)application:(UIApplication*)application
261 didReceiveRemoteNotification:(NSDictionary*)userInfo
262 fetchCompletionHandler:(
void (^)(UIBackgroundFetchResult result))completionHandler {
263 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
267 if ([delegate respondsToSelector:_cmd]) {
268 if ([delegate application:application
269 didReceiveRemoteNotification:userInfo
270 fetchCompletionHandler:completionHandler]) {
277 #pragma GCC diagnostic push
278 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
279 - (void)application:(UIApplication*)application
280 didReceiveLocalNotification:(UILocalNotification*)notification {
281 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
285 if ([delegate respondsToSelector:_cmd]) {
286 [delegate application:application didReceiveLocalNotification:notification];
290 #pragma GCC diagnostic pop
292 - (void)userNotificationCenter:(UNUserNotificationCenter*)center
293 willPresentNotification:(UNNotification*)notification
294 withCompletionHandler:
295 (
void (^)(UNNotificationPresentationOptions options))completionHandler {
296 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
297 if ([delegate respondsToSelector:_cmd]) {
298 [delegate userNotificationCenter:center
299 willPresentNotification:notification
300 withCompletionHandler:completionHandler];
305 - (void)userNotificationCenter:(UNUserNotificationCenter*)center
306 didReceiveNotificationResponse:(UNNotificationResponse*)response
307 withCompletionHandler:(
void (^)(
void))completionHandler {
308 for (id<FlutterApplicationLifeCycleDelegate> delegate in
_delegates) {
309 if ([delegate respondsToSelector:_cmd]) {
310 [delegate userNotificationCenter:center
311 didReceiveNotificationResponse:response
312 withCompletionHandler:completionHandler];
317 - (BOOL)application:(UIApplication*)application
319 options:(NSDictionary<UIApplicationOpenURLOptionsKey,
id>*)options {
320 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
324 if ([delegate respondsToSelector:_cmd]) {
325 if ([delegate application:application openURL:url options:options]) {
333 - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
334 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
338 if ([delegate respondsToSelector:_cmd]) {
339 if ([delegate application:application handleOpenURL:url]) {
347 - (BOOL)application:(UIApplication*)application
349 sourceApplication:(NSString*)sourceApplication
350 annotation:(
id)annotation {
351 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
355 if ([delegate respondsToSelector:_cmd]) {
356 if ([delegate application:application
358 sourceApplication:sourceApplication
359 annotation:annotation]) {
367 - (void)application:(UIApplication*)application
368 performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
369 completionHandler:(
void (^)(BOOL succeeded))completionHandler {
370 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
374 if ([delegate respondsToSelector:_cmd]) {
375 if ([delegate application:application
376 performActionForShortcutItem:shortcutItem
377 completionHandler:completionHandler]) {
384 - (BOOL)application:(UIApplication*)application
385 handleEventsForBackgroundURLSession:(nonnull NSString*)identifier
386 completionHandler:(nonnull
void (^)())completionHandler {
387 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
391 if ([delegate respondsToSelector:_cmd]) {
392 if ([delegate application:application
393 handleEventsForBackgroundURLSession:identifier
394 completionHandler:completionHandler]) {
402 - (BOOL)application:(UIApplication*)application
403 performFetchWithCompletionHandler:(
void (^)(UIBackgroundFetchResult result))completionHandler {
404 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
408 if ([delegate respondsToSelector:_cmd]) {
409 if ([delegate application:application performFetchWithCompletionHandler:completionHandler]) {
417 - (BOOL)application:(UIApplication*)application
418 continueUserActivity:(NSUserActivity*)userActivity
419 restorationHandler:(
void (^)(NSArray*))restorationHandler {
420 for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in
_delegates) {
424 if ([delegate respondsToSelector:_cmd]) {
425 if ([delegate application:application
426 continueUserActivity:userActivity
427 restorationHandler:restorationHandler]) {