Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : FlutterAppDelegate
@interface AppDelegate : FlutterAppDelegate <FlutterImplicitEngineDelegate>

@end
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ @implementation AppDelegate

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// [GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)didInitializeImplicitFlutterEngine:(NSObject<FlutterImplicitEngineBridge> *)engineBridge {
[GeneratedPluginRegistrant registerWithRegistry:engineBridge.pluginRegistry];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,26 @@
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneDelegateClassName</key>
<string>FlutterSceneDelegate</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Future<void> setupFlutterNotifications() async {
}

void showFlutterNotification(RemoteMessage message) {
print('foreground message received: ${message.messageId}');
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
Expand Down Expand Up @@ -179,14 +180,17 @@ class _Application extends State<Application> {
void initState() {
super.initState();

FirebaseMessaging.instance.getInitialMessage().then(
(value) => setState(
() {
_resolved = true;
initialMessage = value?.data.toString();
},
),
);
// Delay getInitialMessage call by 3 seconds
Future.delayed(const Duration(seconds: 3), () {
FirebaseMessaging.instance.getInitialMessage().then(
(value) => setState(
() {
_resolved = true;
initialMessage = value?.data.toString();
},
),
);
});

FirebaseMessaging.onMessage.listen(showFlutterNotification);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ @implementation FLTFirebaseMessagingPlugin {
NSString *_notificationOpenedAppID;
NSString *_foregroundUniqueIdentifier;

// Track if scene delegate connected (for iOS 13+ scene delegate support)
BOOL _sceneDidConnect;

#ifdef __FF_NOTIFICATIONS_SUPPORTED_PLATFORM
API_AVAILABLE(ios(10), macosx(10.14))
__weak id<UNUserNotificationCenterDelegate> _originalNotificationCenterDelegate;
Expand All @@ -59,6 +62,7 @@ - (instancetype)initWithFlutterMethodChannel:(FlutterMethodChannel *)channel
self = [super init];
if (self) {
_initialNotificationGathered = NO;
_sceneDidConnect = NO;
_channel = channel;
_registrar = registrar;
// Application
Expand Down Expand Up @@ -216,22 +220,31 @@ - (void)messaging:(nonnull FIRMessaging *)messaging

#pragma mark - NSNotificationCenter Observers

- (void)application_onDidFinishLaunchingNotification:(nonnull NSNotification *)notification {
// Setup UIApplicationDelegate.
#if TARGET_OS_OSX
NSDictionary *remoteNotification = notification.userInfo[NSApplicationLaunchUserNotificationKey];
#else
NSDictionary *remoteNotification =
notification.userInfo[UIApplicationLaunchOptionsRemoteNotificationKey];
#endif
- (void)setupNotificationHandlingWithRemoteNotification:
(nullable NSDictionary *)remoteNotification {
if (remoteNotification != nil) {
// If remoteNotification exists, it is the notification that opened the app.
_initialNotification =
[FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:remoteNotification];
_initialNotificationID = remoteNotification[@"gcm.message_id"];
_initialNotificationGathered = YES;
[self initialNotificationCallback];
} else if (_sceneDidConnect) {
// For scene delegates, if no notification was found in connectionOptions,
// delay marking as gathered to allow didReceiveRemoteNotification to fire first
// for contentAvailable notifications that caused the app to launch
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
if (!self->_initialNotificationGathered) {
self->_initialNotificationGathered = YES;
[self initialNotificationCallback];
}
});
} else {
// For non-scene delegate apps, mark as gathered immediately
_initialNotificationGathered = YES;
[self initialNotificationCallback];
}
_initialNotificationGathered = YES;
[self initialNotificationCallback];

[GULAppDelegateSwizzler registerAppDelegateInterceptor:self];
[GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods];
Expand Down Expand Up @@ -314,6 +327,17 @@ - (void)application_onDidFinishLaunchingNotification:(nonnull NSNotification *)n
#endif
}

- (void)application_onDidFinishLaunchingNotification:(nonnull NSNotification *)notification {
// Setup UIApplicationDelegate.
#if TARGET_OS_OSX
NSDictionary *remoteNotification = notification.userInfo[NSApplicationLaunchUserNotificationKey];
#else
NSDictionary *remoteNotification =
notification.userInfo[UIApplicationLaunchOptionsRemoteNotificationKey];
#endif
[self setupNotificationHandlingWithRemoteNotification:remoteNotification];
}

#pragma mark - UNUserNotificationCenter Delegate Methods

#ifdef __FF_NOTIFICATIONS_SUPPORTED_PLATFORM
Expand Down Expand Up @@ -473,6 +497,15 @@ - (BOOL)application:(UIApplication *)application
[FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:userInfo];
// Only handle notifications from FCM.
if (userInfo[@"gcm.message_id"]) {
// For scene delegate apps: if this notification arrives during cold launch
// (before initial notification gathering is complete) and no notification was found
// in connectionOptions, this is the notification that caused the launch.
if (_sceneDidConnect && !_initialNotificationGathered && _initialNotification == nil) {
_initialNotification = notificationDict;
_initialNotificationID = userInfo[@"gcm.message_id"];
_initialNotificationGathered = YES;
[self initialNotificationCallback];
}
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
__block BOOL completed = NO;

Expand Down Expand Up @@ -538,24 +571,21 @@ - (BOOL)application:(UIApplication *)application
#pragma mark - SceneDelegate Methods

#if !TARGET_OS_OSX
- (BOOL)scene:(UIScene *)scene
- (void)scene:(UIScene *)scene
willConnectToSession:(UISceneSession *)session
options:(UISceneConnectionOptions *)connectionOptions {
// Handle launch notification if present
NSDictionary *remoteNotification =
connectionOptions.notificationResponse.notification.request.content.userInfo;
if (remoteNotification != nil) {
// If remoteNotification exists, it is the notification that opened the app.
_initialNotification =
[FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:remoteNotification];
_initialNotificationID = remoteNotification[@"gcm.message_id"];
// With scene delegates, the notification can be in notificationResponse if user tapped it
_sceneDidConnect = YES;

NSDictionary *remoteNotification = nil;
if (connectionOptions.notificationResponse != nil) {
// User tapped the notification.
remoteNotification =
connectionOptions.notificationResponse.notification.request.content.userInfo;
}

// Register for remote notifications in scene delegate
// This is critical for getting APNS token when using UISceneDelegate
[[UIApplication sharedApplication] registerForRemoteNotifications];

return YES;
[self setupNotificationHandlingWithRemoteNotification:remoteNotification];
}
#endif

Expand Down
Loading