diff --git a/packages/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/CHANGELOG.md index 471fd9f0489c..92ce3f94741a 100644 --- a/packages/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/CHANGELOG.md @@ -1,3 +1,22 @@ +## 6.0.0 + +* Use `UNUserNotificationCenter` to receive messages on iOS version >= 10. +* **Breaking Change** For iOS versions >= 10, this will cause any other plugin that specifies a + `UNUserNotificationCenterDelegate` to `[UNUserNotificationCenter currentNotificationCenter]` to + stop receiving notifications. To have this plugin work with plugins that specify their own + `UNUserNotificationCenterDelegate`, you can remove the line + ```objectivec + [UNUserNotificationCenter currentNotificationCenter].delegate = // plugin specified delegate + ``` + + and add this line to your iOS project `AppDelegate.m` + + ```objectivec + if (@available(iOS 10.0, *)) { + [UNUserNotificationCenter currentNotificationCenter].delegate = (id) self; + } + ``` + ## 5.1.9 * Fix strict compilation errors. diff --git a/packages/firebase_messaging/README.md b/packages/firebase_messaging/README.md index 619e1c6ed34c..4be723a0d77e 100644 --- a/packages/firebase_messaging/README.md +++ b/packages/firebase_messaging/README.md @@ -141,6 +141,23 @@ To integrate your plugin into the iOS part of your app, follow these steps: 1. Follow the steps in the "[Upload your APNs certificate](https://firebase.google.com/docs/cloud-messaging/ios/client#upload_your_apns_certificate)" section of the Firebase docs. +1. Add the following lines to the `(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` +method in the `AppDelegate.m`/`AppDelegate.swift` of your iOS project. + +Objective-C: +```objectivec +if (@available(iOS 10.0, *)) { + [UNUserNotificationCenter currentNotificationCenter].delegate = (id) self; +} +``` + +Swift: +```swift +if #available(iOS 10.0, *) { + UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate +} +``` + ### Dart/Flutter Integration From your Dart code, you need to import the plugin and instantiate it: @@ -195,6 +212,54 @@ curl https://fcm.googleapis.com/fcm/send -H "Content-Type:application/json" -X P Remove the `notification` property in `DATA` to send a data message. +You could also test this from within Flutter using the [http](https://pub.dev/packages/http) package: + +```dart +// Replace with server token from firebase console settings. +final String serverToken = ''; +final FirebaseMessaging firebaseMessaging = FirebaseMessaging(); + +Future> sendAndRetrieveMessage() async { + await firebaseMessaging.requestNotificationPermissions( + const IosNotificationSettings(sound: true, badge: true, alert: true), + ); + + await http.post( + 'https://fcm.googleapis.com/fcm/send', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'key=$serverToken', + }, + body: jsonEncode( + { + 'notification': { + 'body': 'this is a body', + 'title': 'this is a title' + }, + 'priority': 'high', + 'data': { + 'click_action': 'FLUTTER_NOTIFICATION_CLICK', + 'id': '1', + 'status': 'done' + }, + 'to': await firebaseMessaging.getToken(), + }, + ), + ); + + final Completer> completer = + Completer>(); + + firebaseMessaging.configure( + onMessage: (Map message) async { + completer.complete(message); + }, + ); + + return completer.future; +} +``` + ## Issues and feedback Please file Flutterfire specific issues, bugs, or feature requests in our [issue tracker](https://github.com/FirebaseExtended/flutterfire/issues/new). diff --git a/packages/firebase_messaging/android/gradle.properties b/packages/firebase_messaging/android/gradle.properties deleted file mode 100644 index 8bd86f680510..000000000000 --- a/packages/firebase_messaging/android/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M diff --git a/packages/firebase_messaging/example/android/gradle.properties b/packages/firebase_messaging/example/android/gradle.properties index 08f2b5f91bff..d2032bce8be6 100644 --- a/packages/firebase_messaging/example/android/gradle.properties +++ b/packages/firebase_messaging/example/android/gradle.properties @@ -1,3 +1,4 @@ org.gradle.jvmargs=-Xmx1536M android.enableJetifier=true android.useAndroidX=true +android.enableR8=true diff --git a/packages/firebase_messaging/example/ios/Runner/AppDelegate.m b/packages/firebase_messaging/example/ios/Runner/AppDelegate.m index a4b51c88eb60..bddc7fe2249f 100644 --- a/packages/firebase_messaging/example/ios/Runner/AppDelegate.m +++ b/packages/firebase_messaging/example/ios/Runner/AppDelegate.m @@ -9,6 +9,10 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + if (@available(iOS 10.0, *)) { + [UNUserNotificationCenter currentNotificationCenter].delegate = + (id)self; + } [GeneratedPluginRegistrant registerWithRegistry:self]; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } diff --git a/packages/firebase_messaging/example/test_driver/firebase_messaging.dart b/packages/firebase_messaging/example/test_driver/firebase_messaging.dart index 7ba46b79e733..a6d5c888b6dd 100644 --- a/packages/firebase_messaging/example/test_driver/firebase_messaging.dart +++ b/packages/firebase_messaging/example/test_driver/firebase_messaging.dart @@ -1,4 +1,5 @@ import 'dart:async'; + import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; diff --git a/packages/firebase_messaging/ios/Classes/FirebaseMessagingPlugin.m b/packages/firebase_messaging/ios/Classes/FirebaseMessagingPlugin.m index bee180059867..328c065fe462 100644 --- a/packages/firebase_messaging/ios/Classes/FirebaseMessagingPlugin.m +++ b/packages/firebase_messaging/ios/Classes/FirebaseMessagingPlugin.m @@ -19,6 +19,8 @@ @interface FLTFirebaseMessagingPlugin () details:error.localizedDescription]; } +static NSObject *_registrar; + @implementation FLTFirebaseMessagingPlugin { FlutterMethodChannel *_channel; NSDictionary *_launchNotification; @@ -26,6 +28,7 @@ @implementation FLTFirebaseMessagingPlugin { } + (void)registerWithRegistrar:(NSObject *)registrar { + _registrar = registrar; FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_messaging" binaryMessenger:[registrar messenger]]; @@ -59,22 +62,50 @@ - (instancetype)initWithChannel:(FlutterMethodChannel *)channel { - (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"] boolValue]) { - notificationTypes |= UIUserNotificationTypeSound; - } - if ([arguments[@"alert"] boolValue]) { - notificationTypes |= UIUserNotificationTypeAlert; - } - if ([arguments[@"badge"] boolValue]) { - notificationTypes |= UIUserNotificationTypeBadge; + if (@available(iOS 10.0, *)) { + UNAuthorizationOptions authOptions = 0; + if ([arguments[@"sound"] boolValue]) { + authOptions |= UNAuthorizationOptionSound; + } + if ([arguments[@"alert"] boolValue]) { + authOptions |= UNAuthorizationOptionAlert; + } + if ([arguments[@"badge"] boolValue]) { + authOptions |= UNAuthorizationOptionBadge; + } + + [[UNUserNotificationCenter currentNotificationCenter] + requestAuthorizationWithOptions:authOptions + completionHandler:^(BOOL granted, NSError *_Nullable error) { + if (error) { + result(getFlutterError(error)); + } else { + result([NSNumber numberWithBool:granted]); + } + }]; + } else { + UIUserNotificationType notificationTypes = 0; + if ([arguments[@"sound"] boolValue]) { + notificationTypes |= UIUserNotificationTypeSound; + } + if ([arguments[@"alert"] boolValue]) { + notificationTypes |= UIUserNotificationTypeAlert; + } + if ([arguments[@"badge"] boolValue]) { + notificationTypes |= UIUserNotificationTypeBadge; + } + + UIUserNotificationSettings *settings = + [UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil]; + [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; } - UIUserNotificationSettings *settings = - [UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil]; - [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; - result(nil); + [[UIApplication sharedApplication] registerForRemoteNotifications]; + + if (!@available(iOS 10.0, *)) { + result([NSNumber numberWithBool:YES]); + } } else if ([@"configure" isEqualToString:method]) { [FIRMessaging messaging].shouldEstablishDirectChannel = true; [[UIApplication sharedApplication] registerForRemoteNotifications]; diff --git a/packages/firebase_messaging/lib/firebase_messaging.dart b/packages/firebase_messaging/lib/firebase_messaging.dart index 49699fd4bae9..de6c85e8e6df 100644 --- a/packages/firebase_messaging/lib/firebase_messaging.dart +++ b/packages/firebase_messaging/lib/firebase_messaging.dart @@ -77,14 +77,17 @@ class FirebaseMessaging { /// On iOS, prompts the user for notification permissions the first time /// it is called. /// - /// Does nothing on Android. - void requestNotificationPermissions( - [IosNotificationSettings iosSettings = const IosNotificationSettings()]) { + /// Does nothing and returns null on Android. + FutureOr requestNotificationPermissions([ + IosNotificationSettings iosSettings = const IosNotificationSettings(), + ]) { if (!_platform.isIOS) { - return; + return null; } - _channel.invokeMethod( - 'requestNotificationPermissions', iosSettings.toMap()); + return _channel.invokeMethod( + 'requestNotificationPermissions', + iosSettings.toMap(), + ); } final StreamController _iosSettingsStreamController = diff --git a/packages/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/pubspec.yaml index 42df8c1ba1ad..feb8d4e29efc 100644 --- a/packages/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. author: Flutter Team homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_messaging -version: 5.1.9 +version: 6.0.0 flutter: plugin: