Skip to content

Commit 891ea57

Browse files
bparrishMineskroikie
authored andcommitted
[firebase_messaging] Use UNUserNotificationCenter for ios 10+ (#121)
* Use UNUserNotificationCenter for ios 10+ * Add swift documentation * Move http test to README
1 parent 4af5723 commit 891ea57

File tree

9 files changed

+144
-21
lines changed

9 files changed

+144
-21
lines changed

packages/firebase_messaging/CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
## 6.0.0
2+
3+
* Use `UNUserNotificationCenter` to receive messages on iOS version >= 10.
4+
* **Breaking Change** For iOS versions >= 10, this will cause any other plugin that specifies a
5+
`UNUserNotificationCenterDelegate` to `[UNUserNotificationCenter currentNotificationCenter]` to
6+
stop receiving notifications. To have this plugin work with plugins that specify their own
7+
`UNUserNotificationCenterDelegate`, you can remove the line
8+
```objectivec
9+
[UNUserNotificationCenter currentNotificationCenter].delegate = // plugin specified delegate
10+
```
11+
12+
and add this line to your iOS project `AppDelegate.m`
13+
14+
```objectivec
15+
if (@available(iOS 10.0, *)) {
16+
[UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
17+
}
18+
```
19+
120
## 5.1.9
221
322
* Fix strict compilation errors.

packages/firebase_messaging/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,23 @@ To integrate your plugin into the iOS part of your app, follow these steps:
141141
142142
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.
143143
144+
1. Add the following lines to the `(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`
145+
method in the `AppDelegate.m`/`AppDelegate.swift` of your iOS project.
146+
147+
Objective-C:
148+
```objectivec
149+
if (@available(iOS 10.0, *)) {
150+
[UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
151+
}
152+
```
153+
154+
Swift:
155+
```swift
156+
if #available(iOS 10.0, *) {
157+
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
158+
}
159+
```
160+
144161
### Dart/Flutter Integration
145162

146163
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
195212

196213
Remove the `notification` property in `DATA` to send a data message.
197214

215+
You could also test this from within Flutter using the [http](https://pub.dev/packages/http) package:
216+
217+
```dart
218+
// Replace with server token from firebase console settings.
219+
final String serverToken = '<Server-Token>';
220+
final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
221+
222+
Future<Map<String, dynamic>> sendAndRetrieveMessage() async {
223+
await firebaseMessaging.requestNotificationPermissions(
224+
const IosNotificationSettings(sound: true, badge: true, alert: true),
225+
);
226+
227+
await http.post(
228+
'https://fcm.googleapis.com/fcm/send',
229+
headers: <String, String>{
230+
'Content-Type': 'application/json',
231+
'Authorization': 'key=$serverToken',
232+
},
233+
body: jsonEncode(
234+
<String, dynamic>{
235+
'notification': <String, dynamic>{
236+
'body': 'this is a body',
237+
'title': 'this is a title'
238+
},
239+
'priority': 'high',
240+
'data': <String, dynamic>{
241+
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
242+
'id': '1',
243+
'status': 'done'
244+
},
245+
'to': await firebaseMessaging.getToken(),
246+
},
247+
),
248+
);
249+
250+
final Completer<Map<String, dynamic>> completer =
251+
Completer<Map<String, dynamic>>();
252+
253+
firebaseMessaging.configure(
254+
onMessage: (Map<String, dynamic> message) async {
255+
completer.complete(message);
256+
},
257+
);
258+
259+
return completer.future;
260+
}
261+
```
262+
198263
## Issues and feedback
199264

200265
Please file Flutterfire specific issues, bugs, or feature requests in our [issue tracker](https://github.com/FirebaseExtended/flutterfire/issues/new).

packages/firebase_messaging/android/gradle.properties

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
org.gradle.jvmargs=-Xmx1536M
22
android.enableJetifier=true
33
android.useAndroidX=true
4+
android.enableR8=true

packages/firebase_messaging/example/ios/Runner/AppDelegate.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ @implementation AppDelegate
99

1010
- (BOOL)application:(UIApplication *)application
1111
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
12+
if (@available(iOS 10.0, *)) {
13+
[UNUserNotificationCenter currentNotificationCenter].delegate =
14+
(id<UNUserNotificationCenterDelegate>)self;
15+
}
1216
[GeneratedPluginRegistrant registerWithRegistry:self];
1317
return [super application:application didFinishLaunchingWithOptions:launchOptions];
1418
}

packages/firebase_messaging/example/test_driver/firebase_messaging.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:async';
2+
23
import 'package:flutter_driver/driver_extension.dart';
34
import 'package:flutter_test/flutter_test.dart';
45
import 'package:firebase_messaging/firebase_messaging.dart';

packages/firebase_messaging/ios/Classes/FirebaseMessagingPlugin.m

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ @interface FLTFirebaseMessagingPlugin () <FIRMessagingDelegate>
1919
details:error.localizedDescription];
2020
}
2121

22+
static NSObject<FlutterPluginRegistrar> *_registrar;
23+
2224
@implementation FLTFirebaseMessagingPlugin {
2325
FlutterMethodChannel *_channel;
2426
NSDictionary *_launchNotification;
2527
BOOL _resumingFromBackground;
2628
}
2729

2830
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
31+
_registrar = registrar;
2932
FlutterMethodChannel *channel =
3033
[FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_messaging"
3134
binaryMessenger:[registrar messenger]];
@@ -59,22 +62,50 @@ - (instancetype)initWithChannel:(FlutterMethodChannel *)channel {
5962
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
6063
NSString *method = call.method;
6164
if ([@"requestNotificationPermissions" isEqualToString:method]) {
62-
UIUserNotificationType notificationTypes = 0;
6365
NSDictionary *arguments = call.arguments;
64-
if ([arguments[@"sound"] boolValue]) {
65-
notificationTypes |= UIUserNotificationTypeSound;
66-
}
67-
if ([arguments[@"alert"] boolValue]) {
68-
notificationTypes |= UIUserNotificationTypeAlert;
69-
}
70-
if ([arguments[@"badge"] boolValue]) {
71-
notificationTypes |= UIUserNotificationTypeBadge;
66+
if (@available(iOS 10.0, *)) {
67+
UNAuthorizationOptions authOptions = 0;
68+
if ([arguments[@"sound"] boolValue]) {
69+
authOptions |= UNAuthorizationOptionSound;
70+
}
71+
if ([arguments[@"alert"] boolValue]) {
72+
authOptions |= UNAuthorizationOptionAlert;
73+
}
74+
if ([arguments[@"badge"] boolValue]) {
75+
authOptions |= UNAuthorizationOptionBadge;
76+
}
77+
78+
[[UNUserNotificationCenter currentNotificationCenter]
79+
requestAuthorizationWithOptions:authOptions
80+
completionHandler:^(BOOL granted, NSError *_Nullable error) {
81+
if (error) {
82+
result(getFlutterError(error));
83+
} else {
84+
result([NSNumber numberWithBool:granted]);
85+
}
86+
}];
87+
} else {
88+
UIUserNotificationType notificationTypes = 0;
89+
if ([arguments[@"sound"] boolValue]) {
90+
notificationTypes |= UIUserNotificationTypeSound;
91+
}
92+
if ([arguments[@"alert"] boolValue]) {
93+
notificationTypes |= UIUserNotificationTypeAlert;
94+
}
95+
if ([arguments[@"badge"] boolValue]) {
96+
notificationTypes |= UIUserNotificationTypeBadge;
97+
}
98+
99+
UIUserNotificationSettings *settings =
100+
[UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil];
101+
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
72102
}
73-
UIUserNotificationSettings *settings =
74-
[UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil];
75-
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
76103

77-
result(nil);
104+
[[UIApplication sharedApplication] registerForRemoteNotifications];
105+
106+
if (!@available(iOS 10.0, *)) {
107+
result([NSNumber numberWithBool:YES]);
108+
}
78109
} else if ([@"configure" isEqualToString:method]) {
79110
[FIRMessaging messaging].shouldEstablishDirectChannel = true;
80111
[[UIApplication sharedApplication] registerForRemoteNotifications];

packages/firebase_messaging/lib/firebase_messaging.dart

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,17 @@ class FirebaseMessaging {
7777
/// On iOS, prompts the user for notification permissions the first time
7878
/// it is called.
7979
///
80-
/// Does nothing on Android.
81-
void requestNotificationPermissions(
82-
[IosNotificationSettings iosSettings = const IosNotificationSettings()]) {
80+
/// Does nothing and returns null on Android.
81+
FutureOr<bool> requestNotificationPermissions([
82+
IosNotificationSettings iosSettings = const IosNotificationSettings(),
83+
]) {
8384
if (!_platform.isIOS) {
84-
return;
85+
return null;
8586
}
86-
_channel.invokeMethod<void>(
87-
'requestNotificationPermissions', iosSettings.toMap());
87+
return _channel.invokeMethod<bool>(
88+
'requestNotificationPermissions',
89+
iosSettings.toMap(),
90+
);
8891
}
8992

9093
final StreamController<IosNotificationSettings> _iosSettingsStreamController =

packages/firebase_messaging/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform
33
messaging solution that lets you reliably deliver messages on Android and iOS.
44
author: Flutter Team <[email protected]>
55
homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_messaging
6-
version: 5.1.9
6+
version: 6.0.0
77

88
flutter:
99
plugin:

0 commit comments

Comments
 (0)