FlutterAppDelegate.mm 7.3 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/ftl/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 77 78 79 80 81 82 83 84 85 86 87 88
  // Note the name is not an identifier and multiple instances can exist.
  _debugBackgroundTask = [application
      beginBackgroundTaskWithName:@"Flutter debug task"
                expirationHandler:^{
                  FTL_LOG(WARNING)
                      << "\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"
                         "To reconnect, launch your application again via 'flutter run";
                }];
#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 158
- (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;
      }
    }
  }
}

- (BOOL)application:(UIApplication*)application
159
      handleOpenURL:(NSURL*)url {
160 161
  for (id<FlutterPlugin> plugin in _pluginDelegates) {
    if ([plugin respondsToSelector:_cmd]) {
162
      if ([plugin application:application handleOpenURL:url]) {
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
        return YES;
      }
    }
  }
  return NO;
}

- (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 {
  return (FlutterViewController*)_appDelegate.window.rootViewController;
}

- (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 已提交
223
@end