I am building a Flutter app with Firebase Messaging. I am using AwesomeNotifications plugin to display the notifications.
My notifications is a data only notification, because adding the notification property triggers the default SDK notification as well causing duplicate notifications.
The issue is, if I restarted my iOS device, I no longer receive the data only notification. If I send the same notification with the notification property added, the SDK generated notification get displayed. However if I reopen the app after the restart, the notifications will continue to recieve.
In Android, no issues at all.
I have tested this with iOS 15.3.1 running in iPhone 6s.
Below is my JSON code.
"message": {
"token": recieverFcm,
"data": {
"name": senderName,
"body": "Image Sent",
"chatRoomId": chatRoomId,
"sender_profile_pic": senderProfilePic,
"senderUid": senderUid,
"data_type": messageType,
"image_link": message,
"click_action": "OPEN_CHAT_ROOM"
},
"android": {
"priority": "high"
},
"apns": {
"payload": {
"aps": {
"category": "OPEN_CHAT_ROOM",
"sound": "enable",
"content-available": 1,
}
}
}
}
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
NotificationController _notificationController = NotificationController();
//Initialize firebase
await Firebase.initializeApp();
await _notificationController.startNotificationService();
//Listen for the Token change
FirebaseMessaging.instance.onTokenRefresh.listen((String token) {
print("New token: $token");
});
//Apply MultiProvider
runApp(MultiProvider(
providers: [
//provider lists
],
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
NotificationController _notificationController = NotificationController();
_notificationController.startAwesomeNotificationlistener();
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
textTheme: GoogleFonts.poppinsTextTheme(),
primaryColor: primaryColor,
backgroundColor: Colors.white,
scaffoldBackgroundColor: Colors.white,
accentColor: darkColor,
appBarTheme: AppBarTheme(
backgroundColor: Colors.white,
elevation: 0,
iconTheme: IconThemeData(color: Colors.black),
titleTextStyle: GoogleFonts.poppins(
fontSize: 16, color: darkColor, fontWeight: FontWeight.w500)),
textSelectionTheme: TextSelectionThemeData(cursorColor: darkColor),
outlinedButtonTheme: OutlinedButtonThemeData(style: outlineButtonStyle),
elevatedButtonTheme:
ElevatedButtonThemeData(style: elevatedButtonStyle),
),
routes: {
//Routes go here
},
home: LoadingScreen3(),
);
}
}
notification_controller.dart
class NotificationController {
///Start notification service
Future<void> startNotificationService() async {
NotificationService _notificationService = NotificationService();
await _notificationService.initializFirebaseeNotifications();
}
///Display a new notification in foreground
Future<void> displayNotification({
required String groupKey,
required String channelKey,
required String title,
required String body,
required String summary,
required NotificationLayout layout,
required bool displayOnBackground,
required bool displayOnForeground,
required String messageType,
String? clickAction,
String? chatRoomId,
String? chatMessageFrom,
}) async {
NotificationService _notificationService = NotificationService();
await _notificationService.createAwesomeNotification(
groupKey: groupKey,
channelKey: channelKey,
title: title,
body: body,
summary: summary,
layout: layout,
displayOnBackground: displayOnBackground,
displayOnForeground: displayOnForeground,
messageType: messageType,
clickAction: clickAction,
chatRoomId: chatRoomId,
chatMessageFrom: chatMessageFrom);
}
//Start awesome notification listener
void startAwesomeNotificationlistener() {
NotificationService _notificationService = NotificationService();
_notificationService.startAwesomeNotificationListener();
}
}
notification_service.dart
class NotificationService with ChangeNotifier {
FirebaseMessaging _messaging = FirebaseMessaging.instance;
///Start initializing the notification service
Future<void> initializFirebaseeNotifications() async {
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
//Request permission for firebase messaging
NotificationSettings settings = await _messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
print('User granted permission');
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
developer.log("REMOTE MESSAGE LISTENER");
print("REMOTE MESSAGE LISTENER");
if (message.data["data_type"] == "TEXT") {
await createAwesomeNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: message.data["body"],
summary: message.data["body"],
layout: NotificationLayout.Messaging,
displayOnBackground: true,
displayOnForeground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"]);
} else if (message.data["data_type"] == "IMAGE") {
await createAwesomeNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: Emojis.art_framed_picture + " " + message.data["body"],
summary: message.data["body"],
layout: NotificationLayout.Messaging,
displayOnBackground: true,
displayOnForeground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"],
);
}
});
} else {
print('User declined or has not accepted permission');
}
/// Update the iOS foreground notification presentation options to allow
/// heads up notifications.
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage? message) {
developer.log("REMOTE MESSAGE");
if (message != null) {
developer.log(message.data.toString());
}
});
// For handling notification when the app is in background
// but not terminated
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print("onMessageOpenedApp executed");
});
await initializeAwesomeNotifications();
}
//Initialize the notification display plugin
Future<void> initializeAwesomeNotifications() async {
AwesomeNotifications().initialize('resource://drawable/logo', [
NotificationChannel(
channelGroupKey: 'basic_tests',
channelKey: 'basic_channel',
channelName: 'Basic notifications',
channelDescription: 'Notification channel for basic tests',
defaultColor: Color(0xFF9D50DD),
ledColor: Colors.white,
importance: NotificationImportance.High),
]);
}
//Create and display notification
Future createAwesomeNotification({
required String groupKey,
required String channelKey,
required String title,
required String body,
required String summary,
required NotificationLayout layout,
required bool displayOnBackground,
required bool displayOnForeground,
required String messageType,
String? clickAction,
String? chatRoomId,
String? chatMessageFrom,
}) async {
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: UniqueKey().hashCode,
groupKey: groupKey,
channelKey: channelKey,
title: title,
body: body,
summary: summary,
notificationLayout: layout,
displayOnBackground: displayOnBackground,
displayOnForeground: displayOnForeground,
payload: {
"messageType": messageType,
"clickAction": clickAction ?? "",
"chatRoomId": chatRoomId ?? "",
"chatMessageFrom": chatMessageFrom ?? ""
}),
);
}
//Start Awesome notification listener
void startAwesomeNotificationListener() {
AwesomeNotifications()
.actionStream
.listen((ReceivedNotification receivedNotification) {
developer.log("Notification clicked");
developer.log(receivedNotification.body ?? "no data");
});
}
}
// Declared as global, outside of any class
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
NotificationController _notificationController = NotificationController();
developer.log("background listener called");
print("Handling a background message: ${message.data}");
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
// Use this method to automatically convert the push data, in case you gonna use our data standard
//AwesomeNotifications().createNotificationFromJsonData(message.data);
if (message.data['data_type'].toString().toUpperCase() == "TEXT") {
print("Handling a background message: ${message.data['data_type']}");
await _notificationController.displayNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: message.data["body"],
summary: message.data["body"], // Anything you want here
layout: NotificationLayout.Messaging,
displayOnForeground: true,
displayOnBackground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"]);
} else if (message.data['data_type'].toString().toUpperCase() == "IMAGE") {
Future.delayed(Duration(seconds: 2));
await _notificationController.displayNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: Emojis.art_framed_picture + " " + message.data["body"],
summary: message.data["body"], // Anything you want here
layout: NotificationLayout.Messaging,
displayOnBackground: true,
displayOnForeground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"]);
}
}
How can I fix this issue and continue to receive the data only message even after iOS device restart?