@@ -2,7 +2,7 @@ import 'dart:core';
22import 'dart:typed_data' ;
33import 'dart:ui' ;
44import 'dart:convert' ;
5- import 'package:flutter/services. dart' ;
5+ import 'dart:isolate ' ;
66import 'package:firebase_messaging/firebase_messaging.dart' ;
77import 'package:flutter_local_notifications/flutter_local_notifications.dart' ;
88import 'package:http/http.dart' as http;
@@ -106,6 +106,7 @@ AndroidChannel? _androidChannel;
106106final _activeNotifications = < String , List <String >> {};
107107int _nextId = 0 ;
108108final _showIdFromNotificationId = < String , int > {};
109+ final _receivePort = ReceivePort ();
109110
110111Future <ByteArrayAndroidBitmap ?> _androidBitmapFromUrl (String ? url) async {
111112 if (url == null ) {
@@ -115,7 +116,7 @@ Future<ByteArrayAndroidBitmap?> _androidBitmapFromUrl(String? url) async {
115116 // TODO: maybe we can keep a cache in case _androidBitmapFromUrl gets called
116117 // multiple times with the same URL
117118 final response = await http.get (Uri .parse (url));
118- print ("📘 _androidBitmapFromUrl ($url ): ${ response } " );
119+ print ("📘 _androidBitmapFromUrl ($url ): $response " );
119120 return ByteArrayAndroidBitmap (response.bodyBytes);
120121}
121122
@@ -127,7 +128,7 @@ Future<ByteArrayAndroidIcon?> _androidIconFromUrl(String? url) async {
127128 // TODO: maybe we can keep a cache in case _androidIconFromUrl gets called
128129 // multiple times with the same URL
129130 final response = await http.get (Uri .parse (url));
130- print ("📘 _androidIconFromUrl ($url ): ${ response } " );
131+ print ("📘 _androidIconFromUrl ($url ): $response " );
131132 return ByteArrayAndroidIcon (response.bodyBytes);
132133}
133134
@@ -140,6 +141,13 @@ Future<void> _onFCMBackgroundMessage(RemoteMessage firebaseMessage) async {
140141 print ('📘 Message also contained a notification: ${firebaseMessage .notification }' );
141142 }
142143
144+ // onBackgroundMessage runs on a separate isolate, so we're passing the message to the main isolate
145+ IsolateNameServer .lookupPortByName ('talkjsFCMPort' )? .send (firebaseMessage);
146+ }
147+
148+ Future <void > _onReceiveMessageFromPort (RemoteMessage firebaseMessage) async {
149+ print ("📘 _onReceiveMessageFromPort: ${firebaseMessage .messageId }" );
150+
143151 final data = firebaseMessage.data;
144152 StyleInformation styleInformation;
145153 styleInformation = MessagingStyleInformation (Person (name: 'me' ));
@@ -198,6 +206,7 @@ Future<void> _onFCMBackgroundMessage(RemoteMessage firebaseMessage) async {
198206 }
199207 } else {
200208 print ("📘 _onFCMBackgroundMessage: activeNotifications != null" );
209+ activeNotifications.add (data['talkjs' ]);
201210 final messages = < Message > [];
202211 for (final talkjsString in activeNotifications) {
203212 final Map <String , dynamic > messageTalkjsData = json.decode (talkjsString);
@@ -217,20 +226,6 @@ Future<void> _onFCMBackgroundMessage(RemoteMessage firebaseMessage) async {
217226 );
218227 }
219228
220- final sender = talkjsData['sender' ];
221-
222- messages.add (
223- Message (
224- talkjsData['message' ]['text' ],
225- timestamp,
226- Person (
227- icon: await _androidIconFromUrl (sender['photoUrl' ]),
228- key: sender['id' ],
229- name: sender['name' ],
230- ),
231- ),
232- );
233-
234229 styleInformation = MessagingStyleInformation (
235230 Person (
236231 name: 'me' ,
@@ -278,58 +273,55 @@ Future<void> _onFCMBackgroundMessage(RemoteMessage firebaseMessage) async {
278273 );
279274}
280275
276+ void _onSelectNotification (String ? payload) {
277+ print ('📘 _onSelectNotification: $payload ' );
278+
279+ if (payload != null ) {
280+ final Map <String , dynamic > talkjsData = json.decode (payload);
281+ final String notificationId = talkjsData['conversation' ]['id' ];
282+ _activeNotifications.remove (notificationId);
283+ }
284+ }
285+
281286void _onFCMTokenRefresh (String token) {
282287 print ('📘 Firebase onTokenRefresh: $token ' );
283288
284289 fcmToken = token;
285290}
286291
287292Future <void > registerAndroidPushNotificationHandlers (AndroidChannel androidChannel) async {
288- FirebaseMessaging .onBackgroundMessage (_onFCMBackgroundMessage);
289-
290- FirebaseMessaging .onMessage.listen (_onFCMBackgroundMessage); // Only for testing
291-
292293 // Get the token each time the application loads
293294 fcmToken = await FirebaseMessaging .instance.getToken ();
294295 print ('📘 Firebase token: $fcmToken ' );
295296
296297 // Update the token each time it refreshes
297298 FirebaseMessaging .instance.onTokenRefresh.listen (_onFCMTokenRefresh);
298299
299- await _flutterLocalNotificationsPlugin.initialize (InitializationSettings (
300- android: AndroidInitializationSettings ('@mipmap/ic_launcher' ),
301- ));
300+ await _flutterLocalNotificationsPlugin.initialize (
301+ InitializationSettings (
302+ android: AndroidInitializationSettings ('@mipmap/ic_launcher' ),
303+ ),
304+ onSelectNotification: _onSelectNotification,
305+ );
302306
303307 _androidChannel = androidChannel;
304308
305309 // TODO: Handle already existing notifications
310+ /* Already existing notifications cannot be handled at the moment because
311+ * the ActiveNotification class doesn't have enough information
306312 try {
307313 final activeNotifications = await _flutterLocalNotificationsPlugin
308314 .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
309315 ?.getActiveNotifications();
310-
311- /*
312- for (final displayedNotification in activeNotifications) {
313- const notification = displayedNotification.notification;
314-
315- if (JSON.stringify(notification.data) !== '{}') {
316- let activeNotifications = this.#activeNotifications[notification.id!];
317- if (!activeNotifications) {
318- activeNotifications = [];
319- this.#activeNotifications[notification.id!] = activeNotifications;
320- }
321-
322- const talkjs = JSON.parse(notification.data!.talkjs);
323- activeNotifications.push({
324- sender: talkjs.sender,
325- message: talkjs.message,
326- });
327- }
328- }
329- */
330316 } on PlatformException {
331317 // PlatformException is raised on Android < 6.0
332318 // Simply ignoring this part
333319 }
320+ */
321+
322+ IsolateNameServer .registerPortWithName (_receivePort.sendPort, 'talkjsFCMPort' );
323+ _receivePort.listen ((message) async => await _onReceiveMessageFromPort (message));
324+
325+ FirebaseMessaging .onBackgroundMessage (_onFCMBackgroundMessage);
334326}
335327
0 commit comments