blob: b3b6da4d62d9e9f47cda997942f765815e89c0b9 [file] [log] [blame]
// Copyright 2017 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.
#import "FirebaseMessagingPlugin.h"
#import "Firebase/Firebase.h"
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
@interface FLTFirebaseMessagingPlugin ()<FIRMessagingDelegate>
@end
#endif
@implementation FLTFirebaseMessagingPlugin {
FlutterMethodChannel *_channel;
NSDictionary *_launchNotification;
BOOL _resumingFromBackground;
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FlutterMethodChannel *channel =
[FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_messaging"
binaryMessenger:[registrar messenger]];
FLTFirebaseMessagingPlugin *instance =
[[FLTFirebaseMessagingPlugin alloc] initWithChannel:channel];
[registrar addApplicationDelegate:instance];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (instancetype)initWithChannel:(FlutterMethodChannel *)channel {
self = [super init];
if (self) {
_channel = channel;
_resumingFromBackground = NO;
if (![FIRApp defaultApp]) {
[FIRApp configure];
}
[FIRMessaging messaging].delegate = self;
}
return self;
}
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
NSString *method = call.method;
if ([@"requestNotificationPermissions" isEqualToString:method]) {
UIUserNotificationType notificationTypes = 0;
NSDictionary *arguments = call.arguments;
if (arguments[@"sound"]) {
notificationTypes |= UIUserNotificationTypeSound;
}
if (arguments[@"alert"]) {
notificationTypes |= UIUserNotificationTypeAlert;
}
if (arguments[@"badge"]) {
notificationTypes |= UIUserNotificationTypeBadge;
}
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
result(nil);
} else if ([@"configure" isEqualToString:method]) {
[[UIApplication sharedApplication] registerForRemoteNotifications];
if (_launchNotification != nil) {
[_channel invokeMethod:@"onLaunch" arguments:_launchNotification];
}
result(nil);
} else if ([@"subscribeToTopic" isEqualToString:method]) {
NSString *topic = call.arguments;
[[FIRMessaging messaging] subscribeToTopic:topic];
result(nil);
} else if ([@"unsubscribeFromTopic" isEqualToString:method]) {
NSString *topic = call.arguments;
[[FIRMessaging messaging] unsubscribeFromTopic:topic];
result(nil);
} else {
result(FlutterMethodNotImplemented);
}
}
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// Receive data message on iOS 10 devices while app is in the foreground.
- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage {
[self didReceiveRemoteNotification:remoteMessage.appData];
}
#endif
- (void)didReceiveRemoteNotification:(NSDictionary *)userInfo {
if (_resumingFromBackground) {
[_channel invokeMethod:@"onResume" arguments:userInfo];
} else {
[_channel invokeMethod:@"onMessage" arguments:userInfo];
}
}
#pragma mark - AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (launchOptions != nil) {
_launchNotification = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
}
return YES;
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
_resumingFromBackground = YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
_resumingFromBackground = NO;
// Clears push notifications from the notification center, with the
// side effect of resetting the badge count. We need to clear notifications
// because otherwise the user could tap notifications in the notification
// center while the app is in the foreground, and we wouldn't be able to
// distinguish that case from the case where a message came in and the
// user dismissed the notification center without tapping anything.
// TODO(goderbauer): Revisit this behavior once we provide an API for managing
// the badge number, or if we add support for running Dart in the background.
// Setting badgeNumber to 0 is a no-op (= notifications will not be cleared)
// if it is already 0,
// therefore the next line is setting it to 1 first before clearing it again
// to remove all
// notifications.
application.applicationIconBadgeNumber = 1;
application.applicationIconBadgeNumber = 0;
}
- (bool)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
[self didReceiveRemoteNotification:userInfo];
completionHandler(UIBackgroundFetchResultNoData);
return YES;
}
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
#ifdef DEBUG
[[FIRMessaging messaging] setAPNSToken:deviceToken type:FIRMessagingAPNSTokenTypeSandbox];
#else
[[FIRMessaging messaging] setAPNSToken:deviceToken type:FIRMessagingAPNSTokenTypeProd];
#endif
[_channel invokeMethod:@"onToken" arguments:[[FIRInstanceID instanceID] token]];
}
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
NSDictionary *settingsDictionary = @{
@"sound" : [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeSound],
@"badge" : [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeBadge],
@"alert" : [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeAlert],
};
[_channel invokeMethod:@"onIosSettingsRegistered" arguments:settingsDictionary];
}
- (void)messaging:(nonnull FIRMessaging *)messaging
didRefreshRegistrationToken:(nonnull NSString *)fcmToken {
[_channel invokeMethod:@"onToken" arguments:fcmToken];
}
@end