Skip to content

Commit 1111024

Browse files
committed
[firebase_messaging] Separate onLaunch to an specific method to be able to retrieve launch message in a synchronous way
1 parent fcdb752 commit 1111024

File tree

8 files changed

+98
-15
lines changed

8 files changed

+98
-15
lines changed

packages/firebase_messaging/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 6.0.8
2+
* Separated onLaunch to an specific method to be able to retrieve launch
3+
message in a synchronous way.
4+
* Deprecated the `onLaunch` function from `FirebaseMessaging.configure`.
5+
16
## 6.0.7
27

38
* Remove the deprecated `author:` field from pubspec.yaml

packages/firebase_messaging/README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,18 @@ Next, you should probably request permissions for receiving Push Notifications.
176176

177177
## Receiving Messages
178178

179-
Messages are sent to your Flutter app via the `onMessage`, `onLaunch`, and `onResume` callbacks that you configured with the plugin during setup. Here is how different message types are delivered on the supported platforms:
179+
Launch messages (when application is closed) are retrieved on application init so you can act based on the notification data:
180+
181+
```dart
182+
Map<String, dynamic> message = await _firebaseMessaging.getLaunchMessage();
183+
```
184+
185+
Messages when the application is not in foreground are sent to your Flutter app via the `onMessage` and `onResume` callbacks that you configured with the plugin during setup. Here is how different message types are delivered on the supported platforms:
180186

181187
| | App in Foreground | App in Background | App Terminated |
182188
| --------------------------: | ----------------- | ----------------- | -------------- |
183-
| **Notification on Android** | `onMessage` | Notification is delivered to system tray. When the user clicks on it to open app `onResume` fires if `click_action: FLUTTER_NOTIFICATION_CLICK` is set (see below). | Notification is delivered to system tray. When the user clicks on it to open app `onLaunch` fires if `click_action: FLUTTER_NOTIFICATION_CLICK` is set (see below). |
184-
| **Notification on iOS** | `onMessage` | Notification is delivered to system tray. When the user clicks on it to open app `onResume` fires. | Notification is delivered to system tray. When the user clicks on it to open app `onLaunch` fires. |
189+
| **Notification on Android** | `onMessage` | Notification is delivered to system tray. When the user clicks on it to open app `onResume` fires if `click_action: FLUTTER_NOTIFICATION_CLICK` is set (see below). | Notification is delivered to system tray. When the user clicks on it to open app `getLaunchMessage` fires if `click_action: FLUTTER_NOTIFICATION_CLICK` is set (see below). |
190+
| **Notification on iOS** | `onMessage` | Notification is delivered to system tray. When the user clicks on it to open app `onResume` fires. | Notification is delivered to system tray. When the user clicks on it to open app `getLaunchMessage` fires. |
185191
| **Data Message on Android** | `onMessage` | `onMessage` while app stays in the background. | *not supported by plugin, message is lost* |
186192
| **Data Message on iOS** | `onMessage` | Message is stored by FCM and delivered to app via `onMessage` when the app is brought back to foreground. | Message is stored by FCM and delivered to app via `onMessage` when the app is brought back to foreground. |
187193

packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ public void onComplete(@NonNull Task<InstanceIdResult> task) {
199199
sendMessageFromIntent("onLaunch", mainActivity.getIntent());
200200
}
201201
result.success(null);
202+
} else if ("getLaunchMessage".equals(call.method)) {
203+
if (mainActivity != null) {
204+
Map<String, Object> message = this.getMessageFromIntent(mainActivity.getIntent());
205+
result.success(message);
206+
return;
207+
}
208+
result.success(null);
202209
} else if ("subscribeToTopic".equals(call.method)) {
203210
String topic = call.arguments();
204211
FirebaseMessaging.getInstance()
@@ -300,15 +307,14 @@ public boolean onNewIntent(Intent intent) {
300307
return res;
301308
}
302309

303-
/** @return true if intent contained a message to send. */
304-
private boolean sendMessageFromIntent(String method, Intent intent) {
310+
private Map<String, Object> getMessageFromIntent(Intent intent) {
305311
if (CLICK_ACTION_VALUE.equals(intent.getAction())
306312
|| CLICK_ACTION_VALUE.equals(intent.getStringExtra("click_action"))) {
307313
Map<String, Object> message = new HashMap<>();
308314
Bundle extras = intent.getExtras();
309315

310316
if (extras == null) {
311-
return false;
317+
return null;
312318
}
313319

314320
Map<String, Object> notificationMap = new HashMap<>();
@@ -323,10 +329,20 @@ private boolean sendMessageFromIntent(String method, Intent intent) {
323329

324330
message.put("notification", notificationMap);
325331
message.put("data", dataMap);
332+
return message;
333+
}
334+
return null;
335+
}
326336

327-
channel.invokeMethod(method, message);
328-
return true;
337+
/** @return true if intent contained a message to send. */
338+
private boolean sendMessageFromIntent(String method, Intent intent) {
339+
Map<String, Object> message = this.getMessageFromIntent(intent);
340+
341+
if (message == null) {
342+
return false;
329343
}
330-
return false;
344+
345+
channel.invokeMethod(method, message);
346+
return true;
331347
}
332348
}

packages/firebase_messaging/example/lib/main.dart

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,23 @@ class _PushMessagingExampleState extends State<PushMessagingExample> {
138138
@override
139139
void initState() {
140140
super.initState();
141+
initPushNotifications();
142+
}
143+
144+
void initPushNotifications() async {
145+
final Map<String, dynamic> message =
146+
await _firebaseMessaging.getLaunchMessage();
147+
148+
if (message != null) {
149+
print("getLaunchMessage $message");
150+
_navigateToItemDetail(message);
151+
}
152+
141153
_firebaseMessaging.configure(
142154
onMessage: (Map<String, dynamic> message) async {
143155
print("onMessage: $message");
144156
_showItemDialog(message);
145157
},
146-
onLaunch: (Map<String, dynamic> message) async {
147-
print("onLaunch: $message");
148-
_navigateToItemDetail(message);
149-
},
150158
onResume: (Map<String, dynamic> message) async {
151159
print("onResume: $message");
152160
_navigateToItemDetail(message);

packages/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
124124
[[UIApplication sharedApplication] registerForRemoteNotifications];
125125
result([NSNumber numberWithBool:YES]);
126126
}
127+
} else if ([@"getLaunchMessage" isEqualToString:method]) {
128+
result(_launchNotification);
127129
} else if ([@"configure" isEqualToString:method]) {
128130
[FIRMessaging messaging].shouldEstablishDirectChannel = true;
129131
[[UIApplication sharedApplication] registerForRemoteNotifications];

packages/firebase_messaging/lib/firebase_messaging.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ class FirebaseMessaging {
104104
void configure({
105105
MessageHandler onMessage,
106106
MessageHandler onBackgroundMessage,
107-
MessageHandler onLaunch,
107+
@Deprecated('Use `FirebaseMessaging.getLaunchMessage` instead.')
108+
MessageHandler onLaunch,
108109
MessageHandler onResume,
109110
}) {
110111
_onMessage = onMessage;
@@ -137,6 +138,13 @@ class FirebaseMessaging {
137138
}
138139
}
139140

141+
/// Retrieves the FCM message that launched the application (if any,
142+
/// otherwise returns null).
143+
Future<Map<dynamic, dynamic>> getLaunchMessage() async {
144+
return await _channel
145+
.invokeMethod<Map<dynamic, dynamic>>('getLaunchMessage');
146+
}
147+
140148
final StreamController<String> _tokenStreamController =
141149
StreamController<String>.broadcast();
142150

packages/firebase_messaging/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: firebase_messaging
22
description: Flutter plugin for Firebase Cloud Messaging, a cross-platform
33
messaging solution that lets you reliably deliver messages on Android and iOS.
44
homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_messaging
5-
version: 6.0.7
5+
version: 6.0.8
66

77
flutter:
88
plugin:

packages/firebase_messaging/test/firebase_messaging_test.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// ignore_for_file: deprecated_member_use_from_same_package
6+
57
import 'dart:async';
68

79
import 'package:flutter/services.dart';
@@ -92,6 +94,42 @@ void main() {
9294
expect((await iosSettingsFromStream).toMap(), iosSettings.toMap());
9395
});
9496

97+
test('getLaunchMessage', () async {
98+
final MethodChannel channel =
99+
const MethodChannel('plugins.flutter.io/firebase_messaging');
100+
firebaseMessaging =
101+
FirebaseMessaging.private(channel, const LocalPlatform());
102+
103+
channel.setMockMethodCallHandler((MethodCall methodCall) async {
104+
switch (methodCall.method) {
105+
case 'getLaunchMessage':
106+
return <dynamic, dynamic>{
107+
'notification': <dynamic, dynamic>{
108+
'title': 'Title',
109+
'body': 'Body',
110+
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
111+
},
112+
'data': <dynamic, dynamic>{
113+
'variable1': 'value1',
114+
'variable2': 'value2',
115+
},
116+
};
117+
default:
118+
return null;
119+
}
120+
});
121+
122+
final Map<dynamic, dynamic> message =
123+
await firebaseMessaging.getLaunchMessage();
124+
125+
expect(message['notification']['title'], 'Title');
126+
expect(message['notification']['body'], 'Body');
127+
expect(
128+
message['notification']['click_action'], 'FLUTTER_NOTIFICATION_CLICK');
129+
expect(message['data']['variable1'], 'value1');
130+
expect(message['data']['variable2'], 'value2');
131+
});
132+
95133
test('incoming messages', () async {
96134
final Completer<dynamic> onMessage = Completer<dynamic>();
97135
final Completer<dynamic> onLaunch = Completer<dynamic>();

0 commit comments

Comments
 (0)