7 #import "flutter/fml/logging.h"
30 - (instancetype)init {
31 if (
self = [super init]) {
37 - (BOOL)application:(UIApplication*)application
38 willFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
39 return [
self.lifeCycleDelegate application:application
40 willFinishLaunchingWithOptions:launchOptions];
43 - (BOOL)application:(UIApplication*)application
44 didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
45 return [
self.lifeCycleDelegate application:application
46 didFinishLaunchingWithOptions:launchOptions];
52 if (_rootFlutterViewControllerGetter != nil) {
53 return _rootFlutterViewControllerGetter();
55 UIViewController* rootViewController = _window.rootViewController;
63 - (void)applicationDidEnterBackground:(UIApplication*)application {
67 - (void)applicationWillEnterForeground:(UIApplication*)application {
71 - (void)applicationWillResignActive:(UIApplication*)application {
75 - (void)applicationDidBecomeActive:(UIApplication*)application {
79 - (void)applicationWillTerminate:(UIApplication*)application {
82 #pragma GCC diagnostic push
83 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
84 - (void)application:(UIApplication*)application
85 didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings {
86 [
self.lifeCycleDelegate application:application
87 didRegisterUserNotificationSettings:notificationSettings];
89 #pragma GCC diagnostic pop
91 - (void)application:(UIApplication*)application
92 didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
93 [
self.lifeCycleDelegate application:application
94 didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
97 - (void)application:(UIApplication*)application
98 didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
99 [
self.lifeCycleDelegate application:application
100 didFailToRegisterForRemoteNotificationsWithError:error];
103 #pragma GCC diagnostic push
104 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
105 - (void)application:(UIApplication*)application
106 didReceiveLocalNotification:(UILocalNotification*)notification {
107 [
self.lifeCycleDelegate application:application didReceiveLocalNotification:notification];
109 #pragma GCC diagnostic pop
111 - (void)userNotificationCenter:(UNUserNotificationCenter*)center
112 willPresentNotification:(UNNotification*)notification
113 withCompletionHandler:
114 (
void (^)(UNNotificationPresentationOptions options))completionHandler {
115 if ([
self.lifeCycleDelegate respondsToSelector:_cmd]) {
116 [
self.lifeCycleDelegate userNotificationCenter:center
117 willPresentNotification:notification
118 withCompletionHandler:completionHandler];
125 - (void)userNotificationCenter:(UNUserNotificationCenter*)center
126 didReceiveNotificationResponse:(UNNotificationResponse*)response
127 withCompletionHandler:(
void (^)(
void))completionHandler {
128 if ([
self.lifeCycleDelegate respondsToSelector:_cmd]) {
129 [
self.lifeCycleDelegate userNotificationCenter:center
130 didReceiveNotificationResponse:response
131 withCompletionHandler:completionHandler];
135 - (BOOL)isFlutterDeepLinkingEnabled {
136 NSNumber* isDeepLinkingEnabled =
137 [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"];
139 return isDeepLinkingEnabled ? [isDeepLinkingEnabled boolValue] : YES;
143 - (BOOL)application:(UIApplication*)application
145 options:(NSDictionary<UIApplicationOpenURLOptionsKey,
id>*)options {
146 if ([
self.lifeCycleDelegate application:application openURL:url options:options]) {
151 return [
self handleOpenURL:url options:options relayToSystemIfUnhandled:NO];
155 - (BOOL)handleOpenURL:(NSURL*)url
156 options:(NSDictionary<UIApplicationOpenURLOptionsKey,
id>*)options
157 relayToSystemIfUnhandled:(BOOL)throwBack {
159 if (flutterApplication == nil) {
162 if (![
self isFlutterDeepLinkingEnabled]) {
167 if (flutterViewController) {
168 [flutterViewController sendDeepLinkToFramework:url
169 completionHandler:^(BOOL success) {
170 if (!success && throwBack) {
172 [flutterApplication openURL:url
174 completionHandler:nil];
178 FML_LOG(ERROR) <<
"Attempting to open an URL without a Flutter RootViewController.";
184 - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
185 return [
self.lifeCycleDelegate application:application handleOpenURL:url];
188 - (BOOL)application:(UIApplication*)application
190 sourceApplication:(NSString*)sourceApplication
191 annotation:(
id)annotation {
192 return [
self.lifeCycleDelegate application:application
194 sourceApplication:sourceApplication
195 annotation:annotation];
198 - (void)application:(UIApplication*)application
199 performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
200 completionHandler:(
void (^)(BOOL succeeded))completionHandler {
201 [
self.lifeCycleDelegate application:application
202 performActionForShortcutItem:shortcutItem
203 completionHandler:completionHandler];
206 - (void)application:(UIApplication*)application
207 handleEventsForBackgroundURLSession:(nonnull NSString*)identifier
208 completionHandler:(nonnull
void (^)())completionHandler {
209 [
self.lifeCycleDelegate application:application
210 handleEventsForBackgroundURLSession:identifier
211 completionHandler:completionHandler];
215 - (BOOL)application:(UIApplication*)application
216 continueUserActivity:(NSUserActivity*)userActivity
218 (
void (^)(NSArray<
id<UIUserActivityRestoring>>* __nullable restorableObjects))
220 if ([
self.lifeCycleDelegate application:application
221 continueUserActivity:userActivity
222 restorationHandler:restorationHandler]) {
226 return [
self handleOpenURL:userActivity.webpageURL options:@{} relayToSystemIfUnhandled:YES];
229 #pragma mark - FlutterPluginRegistry methods. All delegating to the rootViewController
233 if (flutterRootViewController) {
234 return [[flutterRootViewController
pluginRegistry] registrarForPlugin:pluginKey];
239 - (BOOL)hasPlugin:(NSString*)pluginKey {
241 if (flutterRootViewController) {
242 return [[flutterRootViewController
pluginRegistry] hasPlugin:pluginKey];
247 - (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey {
249 if (flutterRootViewController) {
250 return [[flutterRootViewController
pluginRegistry] valuePublishedByPlugin:pluginKey];
255 #pragma mark - Selectors handling
258 [
self.lifeCycleDelegate addDelegate:delegate];
261 #pragma mark - UIApplicationDelegate method dynamic implementation
263 - (BOOL)respondsToSelector:(
SEL)selector {
264 if ([
self.lifeCycleDelegate isSelectorAddedDynamically:selector]) {
265 return [
self delegateRespondsSelectorToPlugins:selector];
267 return [
super respondsToSelector:selector];
270 - (BOOL)delegateRespondsSelectorToPlugins:(
SEL)selector {
271 if ([
self.lifeCycleDelegate hasPluginThatRespondsToSelector:selector]) {
272 return [
self.lifeCycleDelegate respondsToSelector:selector];
278 - (id)forwardingTargetForSelector:(
SEL)aSelector {
279 if ([
self.lifeCycleDelegate isSelectorAddedDynamically:aSelector]) {
280 [
self logCapabilityConfigurationWarningIfNeeded:aSelector];
281 return self.lifeCycleDelegate;
283 return [
super forwardingTargetForSelector:aSelector];
290 - (void)logCapabilityConfigurationWarningIfNeeded:(
SEL)selector {
291 NSArray* backgroundModesArray =
292 [[NSBundle mainBundle] objectForInfoDictionaryKey:kUIBackgroundMode];
293 NSSet* backgroundModesSet = [[NSSet alloc] initWithArray:backgroundModesArray];
294 if (selector ==
@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)) {
297 @"You've implemented -[<UIApplicationDelegate> "
298 @"application:didReceiveRemoteNotification:fetchCompletionHandler:], but you still need "
299 @"to add \"remote-notification\
" to the list of your supported UIBackgroundModes in your "
302 }
else if (selector ==
@selector(application:performFetchWithCompletionHandler:)) {
304 NSLog(
@"You've implemented -[<UIApplicationDelegate> "
305 @"application:performFetchWithCompletionHandler:], but you still need to add \"fetch\
" "
306 @"to the list of your supported UIBackgroundModes in your Info.plist.");
311 #pragma mark - State Restoration
313 - (BOOL)application:(UIApplication*)application shouldSaveApplicationState:(NSCoder*)coder {
314 [coder encodeInt64:self.lastAppModificationTime forKey:kRestorationStateAppModificationKey];
318 - (BOOL)application:(UIApplication*)application shouldRestoreApplicationState:(NSCoder*)coder {
319 int64_t stateDate = [coder decodeInt64ForKey:kRestorationStateAppModificationKey];
320 return self.lastAppModificationTime == stateDate;
323 - (BOOL)application:(UIApplication*)application shouldSaveSecureApplicationState:(NSCoder*)coder {
324 [coder encodeInt64:self.lastAppModificationTime forKey:kRestorationStateAppModificationKey];
328 - (BOOL)application:(UIApplication*)application
329 shouldRestoreSecureApplicationState:(NSCoder*)coder {
330 int64_t stateDate = [coder decodeInt64ForKey:kRestorationStateAppModificationKey];
331 return self.lastAppModificationTime == stateDate;
334 - (int64_t)lastAppModificationTime {
336 NSError* error = nil;
337 [[[NSBundle mainBundle] executableURL] getResourceValue:&fileDate
338 forKey:NSURLContentModificationDateKey
340 NSAssert(error == nil,
@"Cannot obtain modification date of main bundle: %@", error);
341 return [fileDate timeIntervalSince1970];
static NSString *const kRemoteNotificationCapabitiliy
static FLUTTER_ASSERT_ARC NSString *const kUIBackgroundMode
static NSString *const kBackgroundFetchCapatibility
static NSString *const kRestorationStateAppModificationKey
FlutterViewController *(^ rootFlutterViewControllerGetter)(void)
UIApplication * application
id< FlutterPluginRegistry > pluginRegistry()