FlutterAppDelegate.mm 9.0 KB
Newer Older
C
Chinmay Garde 已提交
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h"
6
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
7
#include "lib/fxl/logging.h"
C
Chinmay Garde 已提交
8

9 10 11 12 13 14 15 16 17
@interface FlutterAppDelegate ()
@property(readonly, nonatomic) NSMutableArray* pluginDelegates;
@property(readonly, nonatomic) NSMutableDictionary* pluginPublications;
@end

@interface FlutterAppDelegateRegistrar : NSObject<FlutterPluginRegistrar>
- (instancetype)initWithPlugin:(NSString*)pluginKey appDelegate:(FlutterAppDelegate*)delegate;
@end

18 19 20
@implementation FlutterAppDelegate {
  UIBackgroundTaskIdentifier _debugBackgroundTask;
}
C
Chinmay Garde 已提交
21

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
- (instancetype)init {
  if (self = [super init]) {
    _pluginDelegates = [NSMutableArray new];
    _pluginPublications = [NSMutableDictionary new];
  }
  return self;
}

- (void)dealloc {
  [_pluginDelegates release];
  [_pluginPublications release];
  [super dealloc];
}

- (BOOL)application:(UIApplication*)application
    didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      if (![plugin application:application didFinishLaunchingWithOptions:launchOptions]) {
        return NO;
      }
    }
  }
  return YES;
}

48 49 50
// Returns the key window's rootViewController, if it's a FlutterViewController.
// Otherwise, returns nil.
- (FlutterViewController*)rootFlutterViewController {
51
  UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
52 53 54 55 56 57
  if ([viewController isKindOfClass:[FlutterViewController class]]) {
    return (FlutterViewController*)viewController;
  }
  return nil;
}

58
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
59 60 61 62 63 64 65 66
  [super touchesBegan:touches withEvent:event];

  // Pass status bar taps to key window Flutter rootViewController.
  if (self.rootFlutterViewController != nil) {
    [self.rootFlutterViewController handleStatusBarTouches:event];
  }
}

67
- (void)applicationDidEnterBackground:(UIApplication*)application {
68 69
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
  // The following keeps the Flutter session alive when the device screen locks
70
  // in debug mode. It allows continued use of features like hot reload and
71 72
  // taking screenshots once the device unlocks again.
  //
73 74 75 76
  // Note the name is not an identifier and multiple instances can exist.
  _debugBackgroundTask = [application
      beginBackgroundTaskWithName:@"Flutter debug task"
                expirationHandler:^{
77
                  FXL_LOG(WARNING)
78 79 80
                      << "\nThe OS has terminated the Flutter debug connection for being "
                         "inactive in the background for too long.\n\n"
                         "There are no errors with your Flutter application.\n\n"
X
xster 已提交
81
                         "To reconnect, launch your application again via 'flutter run'";
82 83 84 85 86 87 88
                }];
#endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      [plugin applicationDidEnterBackground:application];
    }
  }
89 90
}

91 92 93
- (void)applicationWillEnterForeground:(UIApplication*)application {
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
  [application endBackgroundTask:_debugBackgroundTask];
94
#endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      [plugin applicationWillEnterForeground:application];
    }
  }
}

- (void)applicationWillResignActive:(UIApplication*)application {
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      [plugin applicationWillResignActive:application];
    }
  }
}

- (void)applicationDidBecomeActive:(UIApplication*)application {
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      [plugin applicationDidBecomeActive:application];
    }
  }
}

- (void)applicationWillTerminate:(UIApplication*)application {
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      [plugin applicationWillTerminate:application];
    }
  }
}

- (void)application:(UIApplication*)application
    didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings {
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      [plugin application:application didRegisterUserNotificationSettings:notificationSettings];
    }
  }
}
134

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
- (void)application:(UIApplication*)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      [plugin application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
    }
  }
}

- (void)application:(UIApplication*)application
    didReceiveRemoteNotification:(NSDictionary*)userInfo
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      if ([plugin application:application
              didReceiveRemoteNotification:userInfo
                    fetchCompletionHandler:completionHandler]) {
        return;
      }
    }
  }
}

158 159 160 161 162
- (BOOL)application:(UIApplication*)application
            openURL:(NSURL*)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options {
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
163
      if ([plugin application:application openURL:url options:options]) {
164 165 166 167 168 169 170
        return YES;
      }
    }
  }
  return NO;
}

171
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
172 173
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
174
      if ([plugin application:application handleOpenURL:url]) {
175 176 177 178 179 180 181
        return YES;
      }
    }
  }
  return NO;
}

182
- (BOOL)application:(UIApplication*)application
183 184 185
              openURL:(NSURL*)url
    sourceApplication:(NSString*)sourceApplication
           annotation:(id)annotation {
186 187 188
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      if ([plugin application:application
189 190 191
                        openURL:url
              sourceApplication:sourceApplication
                     annotation:annotation]) {
192 193 194 195 196 197 198
        return YES;
      }
    }
  }
  return NO;
}

199 200 201 202 203 204 205 206 207 208 209 210 211 212
- (void)application:(UIApplication*)application
    performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
               completionHandler:(void (^)(BOOL succeeded))completionHandler {
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
      if ([plugin application:application
              performActionForShortcutItem:shortcutItem
                         completionHandler:completionHandler]) {
        return;
      }
    }
  }
}

213 214
// TODO(xster): move when doing https://github.com/flutter/flutter/issues/3671.
- (NSObject<FlutterBinaryMessenger>*)binaryMessenger {
215 216 217 218 219
  UIViewController* rootViewController = _window.rootViewController;
  if ([rootViewController conformsToProtocol:@protocol(FlutterBinaryMessenger)]) {
    return (NSObject<FlutterBinaryMessenger>*)rootViewController;
  }
  return nil;
220 221
}

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
- (NSObject<FlutterPluginRegistrar>*)registrarForPlugin:(NSString*)pluginKey {
  NSAssert(self.pluginPublications[pluginKey] == nil, @"Duplicate plugin key: %@", pluginKey);
  self.pluginPublications[pluginKey] = [NSNull null];
  return
      [[[FlutterAppDelegateRegistrar alloc] initWithPlugin:pluginKey appDelegate:self] autorelease];
}

- (BOOL)hasPlugin:(NSString*)pluginKey {
  return _pluginPublications[pluginKey] != nil;
}

- (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey {
  return _pluginPublications[pluginKey];
}
@end

@implementation FlutterAppDelegateRegistrar {
  NSString* _pluginKey;
  FlutterAppDelegate* _appDelegate;
}

- (instancetype)initWithPlugin:(NSString*)pluginKey appDelegate:(FlutterAppDelegate*)appDelegate {
  self = [super init];
  NSAssert(self, @"Super init cannot be nil");
  _pluginKey = [pluginKey retain];
  _appDelegate = [appDelegate retain];
  return self;
}

- (void)dealloc {
  [_pluginKey release];
  [_appDelegate release];
  [super dealloc];
}

- (NSObject<FlutterBinaryMessenger>*)messenger {
258
  return [_appDelegate binaryMessenger];
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
}

- (void)publish:(NSObject*)value {
  _appDelegate.pluginPublications[_pluginKey] = value;
}

- (void)addMethodCallDelegate:(NSObject<FlutterPlugin>*)delegate
                      channel:(FlutterMethodChannel*)channel {
  [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
    [delegate handleMethodCall:call result:result];
  }];
}

- (void)addApplicationDelegate:(NSObject<FlutterPlugin>*)delegate {
  [_appDelegate.pluginDelegates addObject:delegate];
}
C
Chinmay Garde 已提交
275
@end