Not able to handle custom notification in Flutter Firebase Cloud Messaging - android

I have create a custom notification using flutter_local_notification package , when I
send notification using FCM, two notifications are visible in both foreground and background state of application. When I click on FCM generated notification its works as usual , but while clicking on custom background notification my app start but am not able to run my logics, so please help me in handling the background custom notification
On clicking background custom notification it shows below info
Attempted to start a duplicate background isolate. Returning...
class NotificationService {
static final NotificationService _notificationService =
NotificationService._private();
NotificationService._private();
factory NotificationService() => _notificationService;
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
final AndroidNotificationChannel _androidChannel =
const AndroidNotificationChannel(
'high_importance_channel', // id
'Notifications', // title
description: 'important notification channel', // description
importance: Importance.high,
playSound: true);
final AndroidInitializationSettings _initializationSettingsAndroid =
const AndroidInitializationSettings(
'app_icon',
);
///This functions initializes Flutterlocalnotificationplugin with required settings and channels
initialize() async {
AndroidFlutterLocalNotificationsPlugin? resp =
flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>();
await resp!.createNotificationChannel(_androidChannel);
resp.requestPermission();
var initializationSettings =
InitializationSettings(android: _initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onDidReceiveNotificationResponse: _handleForegroundNotification,
onDidReceiveBackgroundNotificationResponse:
_handleBackgroundNotification);
}
/// This function create the custom notifcation.
/// before calling this function , firebaseLocalNotification instance should be initialized
showNotification(RemoteMessage message) {
var initializationSettings =
InitializationSettings(android: _initializationSettingsAndroid);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onDidReceiveNotificationResponse: _handleForegroundNotification,
onDidReceiveBackgroundNotificationResponse:
_handleBackgroundNotification);
flutterLocalNotificationsPlugin.show(
1123,
message.data['title'],
message.data['body'],
const NotificationDetails(
android: AndroidNotificationDetails(
'1123',
'channel.name',
channelDescription: 'channel.description',
color: Colors.blue,
playSound: true,
),
));
}
}
///This functions handle background notification press and performs given instructions
#pragma('vm:entry-point')
_handleBackgroundNotification(NotificationResponse response) async {
await Future.delayed(Duration(seconds: 3));
Fluttertoast.showToast(
msg: "backgrrrround call nice no",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
///This functions handel foregroud notification press and performs given instruction
_handleForegroundNotification(NotificationResponse response) async {
await Future.delayed(Duration(seconds: 3));
Fluttertoast.showToast(
msg: "Forerground call nice no",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
and another class for managing FCM
class FCMService {
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
String? fcmToken;
///This function initialized FCM and start stream of token,foregroundmessage,backgroundmessage
initialize() async {
fcmToken = await FirebaseMessaging.instance.getToken();
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
debugPrint(fcmToken);
_listenToTokenStream();
_listenToForegroundMessage();
}
// /Handle background but not teminated app notification press
_listenToOnMessageOpenedApp() {
//when
FirebaseMessaging.onMessageOpenedApp.listen((message) {
print("FCM>>>>>>>> backgroud");
});
}
/// Request permission for higher sdk version
_requestNotificationPermission() async {
NotificationSettings settings = await _firebaseMessaging.requestPermission(
alert: true,
sound: true,
);
debugPrint('User granted permission: ${settings.authorizationStatus}');
}
/// listen to foreground message recieved from FCM
_listenToForegroundMessage() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
NotificationService().showNotification(message);
});
}
///Listen to streamm of token when token expires helps us to updat it
_listenToTokenStream() {
FirebaseMessaging.instance.onTokenRefresh.listen((token) {
fcmToken = token;
debugPrint(fcmToken);
}).onError((e) {
debugPrint("token refresh failed");
});
}
}
///listen background message recieve from FCM , DO NOT: perform heavy task in background
///otherwise your process may get killed
Future<void> fcmBackgroundMessageHandler(RemoteMessage message) async {
await Firebase.initializeApp();
// await NotificationService().initialize();
NotificationService().showNotification(message);
}
main method :
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FCMService().initialize();
NotificationService().initialize();
FirebaseMessaging.onBackgroundMessage(fcmBackgroundMessageHandler);
runApp(const MyApp());
}

you should listen to background messages on FCM initialization But you are doing it on main. SO remove that and add the option in FCM initialization.
I have updated your code with the required updates.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FCMService().initialize();
NotificationService().initialize();
runApp(const MyApp());
}
/// fcm background message handler
Future<void> fcmBackgroundMessageHandler(RemoteMessage message) async {
print(message.notification!.title);
// NotificationService().showNotification(message);
}
class FCMService {
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
String? fcmToken;
///This function initialized FCM and start stream of token,foregroundmessage,backgroundmessage
initialize() async {
fcmToken = await FirebaseMessaging.instance.getToken();
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
debugPrint(fcmToken);
_listenToTokenStream();
_listenToForegroundMessage();
_listenToBackgroundMessage();
}
/// handle push notification events on background
void handlePushNotificationBackgroundEvents() {
FirebaseMessaging.onBackgroundMessage(fcmBackgroundMessageHandler);
}
// /Handle background but not teminated app notification press
_listenToOnMessageOpenedApp() {
//when
FirebaseMessaging.onMessageOpenedApp.listen((message) {
print("FCM>>>>>>>> backgroud");
});
}
/// Request permission for higher sdk version
_requestNotificationPermission() async {
NotificationSettings settings = await _firebaseMessaging.requestPermission(
alert: true,
sound: true,
);
debugPrint('User granted permission: ${settings.authorizationStatus}');
}
/// listen to foreground message recieved from FCM
_listenToForegroundMessage() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
NotificationService().showNotification(message);
});
}
///Listen to streamm of token when token expires helps us to updat it
_listenToTokenStream() {
FirebaseMessaging.instance.onTokenRefresh.listen((token) {
fcmToken = token;
debugPrint(fcmToken);
}).onError((e) {
debugPrint("token refresh failed");
});
}
}

Related

How can I save firebase push notification device local when app closed in flutter?

I use Hive_flutter and flutter_local_notifications: ^13.0.0. And I don't have any about saving notifications device local idea when app closed. Can you help me? thanks for your insteresting.
int badgesCount = 0;
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
FirebaseMessaging messaging = FirebaseMessaging.instance;
class PushNotificationsService {
Future initialise() async {
iOSPermission();
messaging.getToken().then((token) async {
print('token is $token');
});
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('#drawable/ic_stat_name');
DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveIos);
InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (payload) async {
if (payload != "") {
log(payload.toString());
}
},
);
FirebaseMessaging.onMessage.listen(
(RemoteMessage message) async {
if (message.notification != null) {
badgeCount += 1;
final remoteModel = RemoteMessageModel.fromJson(message.toMap());
await StorageHiveHelper().save(remoteModel);
var data = message.notification;
var title = data?.title.toString();
var body = data?.body.toString();
var image = message.data['image'] ?? '';
var type = message.data['type'] ?? '';
var id = '';
id = message.data['type_id'] ?? '';
if (Platform.isIOS) return;
if (image != null && image != 'null' && image != '') {
return await generateImageNotication(
title ?? "", body ?? "", image, type, id);
}
}
},
);
messaging.getInitialMessage().then((RemoteMessage? message) {
if (message != null) {
log("Initial Message: " + (message.data.toString()));
pushToNavigate(message);
}
});
FirebaseMessaging.onMessageOpenedApp
.listen((RemoteMessage message) => pushToNavigate(message));
FirebaseMessaging.onBackgroundMessage(getBackGroundMessage);
}
pushToNavigate(RemoteMessage? message) async {
var type = await message?.data['type'] ?? '';
log("OnDidReceiveIOS: " + (message?.data.toString() ?? "null ios payload"));
log(type);
if (type == 'products') {
navService.pushNamed("product/detail", args: 631509);
}
}
void iOSPermission() async {
await messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
void onDidReceiveIos(
int id, String? title, String? body, String? payload) async {
log("OnDidReceiveIOS: " + (payload?.toLowerCase() ?? "null ios payload"));
try {
var iosDetail = const DarwinNotificationDetails(
presentBadge: true,
presentAlert: false,
presentSound: true,
sound: "cash.caf");
var platformChannelSpecifics = NotificationDetails(iOS: iosDetail);
await flutterLocalNotificationsPlugin.show(
id, title, title, platformChannelSpecifics,
payload: jsonEncode(payload ?? {}));
} on Exception catch (e) {
debugPrint(e.toString());
}
}
I tried saving the message to hive here. It working when app is on but it was not working when the app was totally closed
Future<void> getBackGroundMessage(RemoteMessage message) async {
badgeCount += 1;
await FlutterAppBadger.updateBadgeCount(badgeCount);
final remoteModel = RemoteMessageModel.fromJson(message.toMap());
await StorageHiveHelper().save(remoteModel);
}
}
const String _sound = "notification_sound";
void display(
RemoteMessage message,
NotificationDetails notificationDetails,
) async {
try {
await flutterLocalNotificationsPlugin.show(
message.hashCode,
message.notification?.title,
message.notification?.body,
notificationDetails,
payload: jsonEncode(message.data),
);
} on Exception catch (e) {
debugPrint(e.toString());
}
}
Future<void> generateSimpleNotication(
String title, String msg, String type, String id, RemoteMessage pay) async {
try {
if (Platform.isIOS) return;
log("Payload" + (pay.toMap().toString()));
final id = DateTime.now().millisecondsSinceEpoch ~/ 1000;
var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
'high_importance_channels',
'High Importance Notifications',
playSound: true,
sound: RawResourceAndroidNotificationSound(_sound),
largeIcon: DrawableResourceAndroidBitmap('#drawable/ic_stat_name'),
importance: Importance.max,
priority: Priority.max, );
var iosDetail = const DarwinNotificationDetails(
presentAlert: true, presentSound: true, sound: "cash.caf");
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iosDetail);
await flutterLocalNotificationsPlugin.show(
id, title, msg, platformChannelSpecifics,
payload: jsonEncode(pay.data));
} on Exception catch (e) {
debugPrint(e.toString());
}
}
I don't understand the main problem. You just want to display the notifications when app is closed or in background? Or you really need to save them to the local database? Anyways, try using this class
import 'dart:async';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class PushNotificationService {
static FirebaseMessaging messaging = FirebaseMessaging.instance;
static final FlutterLocalNotificationsPlugin notificationPlugin =
FlutterLocalNotificationsPlugin();
static const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description:
'This channel is used for important notifications.', // description
importance: Importance.high,
);
static String? idPush;
static StreamController<RemoteMessage> _messageStream =
StreamController.broadcast();
static Stream<RemoteMessage> get messagesStream => _messageStream.stream;
static Future _backgroundHandler(RemoteMessage message) async {
_messageStream.add(message);
// implement your actions here
}
static Future _onMessageHandler(RemoteMessage message) async {
_messageStream.add(message);
// implement your actions here, if you want to use flutter_local_notifications, use the display() method.
}
static Future _onMessageOpenApp(RemoteMessage message) async {
_messageStream.add(message);
// implement your actions here
}
// iniciar firebase i notificacions locals
static Future initializeApp() async {
//Push notifications
await Firebase.initializeApp();
idPush = await FirebaseMessaging.instance.getToken();
print('idPush: $idPush');
//Handler
FirebaseMessaging.onBackgroundMessage(_backgroundHandler);
FirebaseMessaging.onMessage.listen(_onMessageHandler);
FirebaseMessaging.onMessageOpenedApp.listen(_onMessageOpenApp);
//local notifications initialization
const InitializationSettings initializationSettings =
InitializationSettings(
iOS: DarwinInitializationSettings(),
android: AndroidInitializationSettings("#mipmap/ic_notification"),
);
notificationPlugin.initialize(initializationSettings);
}
// mètode per obrir una notificació local (només amb l'app oberta)
static void display(RemoteMessage message) async {
try {
await notificationPlugin.show(
message.notification!.hashCode,
message.notification!.title,
message.notification!.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
color: Colors.blue,
icon: '#mipmap/ic_notification',
),
iOS: const DarwinNotificationDetails(
presentAlert: true, presentBadge: true, presentSound: true),
),
);
} on Exception catch (e) {
print(e);
}
}
// demanar permisos
Future<void> requestPermission() async {
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');
} else if (settings.authorizationStatus ==
AuthorizationStatus.provisional) {
print('User granted provisional permission');
} else {
print('User declined or has not accepted permission');
}
}
static closeStreams() {
_messageStream.close();
}
}
This class will show notifications when app is closed or in background. And if you need to display them with the app opened, you can throught the display method. If you want to save them to hive, just implement that part on the Handlers.
Finally initialize the class in your main:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await PushNotificationService.initializeApp();
runApp(const MyApp());
}

Flutter two main call stack created after adding FirebaseMessaging for Notification

enter image description hereI am new to Flutter and as I have added Firebase Messaging in my project for notification, it started to have 2 main call stacks. I am using Flutter sdk >=2.17.6<3.0.0, firebase_messaging: ^14.0.3, and flutter_local_notifications: ^12.0.3. Please give me some help if anyone understand the issue here.
Here is my main dart for runApp:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
//notification
await firebaseMessaging.getInitialMessage();
FirebaseMessaging.onBackgroundMessage(backgroundMessagesHandler);
//Set screen orientation to potrait
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
runApp(const MyApp());
}
And here is my backgroundMessaging function definition:
Future<void> backgroundMessagesHandler(RemoteMessage message) async {
await setupFlutterNotifications();
showFlutterNotification(message);
debugPrint(
"Background Message: ${message.notification!.title} ** ${message.notification!.body}");
}
late AndroidNotificationChannel channel;
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
final firebaseMessaging = FirebaseMessaging.instance;
bool isFlutterLocalNotificationsInitialized = false;
Future<void> setupFlutterNotifications() async {
if (isFlutterLocalNotificationsInitialized) {
return;
}
channel = const AndroidNotificationChannel(
'Demo', // id
'Demo', // title
description: 'Welcome.', // description
importance: Importance.high,
);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await firebaseMessaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
isFlutterLocalNotificationsInitialized = true;
}
I have tried restructuring the main run app by removing async but the problem still remain
The call stack issue

Flutter App Firebase push notification not coming in background

I am facing issue received notifications when app terminated/Remove from recent apps from background.
I have complete all the setup required for android app in build.gradle files both app or project level. I am able to receive push notification when app is open or when app is in the recent apps.
Library versions
firebase_messaging: ^11.2.0
firebase_core: ^1.10.0
flutter_local_notifications: ^9.1.4
here is my code.
await Firebase.initializeApp();
FirebaseMessaging messaging = FirebaseMessaging.instance;
messaging.getToken().then((value) {
print('firebase token =$value');
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
//print(event.notification!.body);
RemoteNotification? notification = message.notification;
if (notification != null) {
print("Notification received when app in foreground");
}
});
FirebaseMessaging.onMessageOpenedApp.listen((message) {
print('Message clicked!');
});
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
BackgroundMessage handler code is below
Future<void> _messageHandler(RemoteMessage message) async {
await Firebase.initializeApp();
RemoteNotification? notification = message.notification;
if (notification != null) {
print("Notification received when app in background");
}
}
Below is my complete code of main.dart file
Future<void> _messageHandler(RemoteMessage message) async {
await Firebase.initializeApp();
RemoteNotification? notification = message.notification;
if (notification != null) {
print("Notification received when app in background");
}
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_messageHandler);
runApp(MyApp());
}
class MyApp extends StatefulWidget {
createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool isUserLoggedIn = true;
bool isLogoutAlertShown = false;
final materialAppKey = GlobalKey();
late FirebaseMessaging messaging;
#override
void initState() {
super.initState();
setUpNotification();
}
setUpNotification() async {
messaging = FirebaseMessaging.instance;
messaging.getToken().then((value) {
print('firebase token =$value');
//sendTokenToServer(value);
Pref.setFcmToken(token: '$value');
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
//print(event.notification!.body);
RemoteNotification? notification = message.notification;
if (notification != null) {
print("Notification received when app in foreground");
}
});
FirebaseMessaging.onMessageOpenedApp.listen((message) {
print('Message clicked!');
});
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
#override
Widget build(BuildContext context) {
return _materialApp();
}
Widget _materialApp() {
return FutureBuilder(
future: _loginState(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return MaterialApp(
debugShowCheckedModeBanner: false,
key: materialAppKey,
darkTheme: AppTheme.lightTheme,
theme: AppTheme.lightTheme,
home: isUserLoggedIn == true ?
BottomNavigationContainer() : LoginOptions(),
);
} else {
return Container(color: Colors.white);
}
});
}
Future<void> _loginState() async {
final token = await Pref.getToken();
isUserLoggedIn = token.length > 0 ? true : false;
}
}
Suggest me what I am missing or doing wrong.
Thank to all for your response.
I Found the solution that why my background handler not working because I am running my app in Debugging mode. As per the FlutterFire Cloud messaging Doc background method not work in Debugging mode if you kill your app.
You can test your background handler method by run your application in debug and then background it by switching apps so it's no longer in the foreground.
If You want to check After app terminate/kill from recent task then Run app in Release Mode. It Works fine
Again thanks to All.

Firebase cloud message - head up notifcation, android and ios

I'm using Firebase notifications, with flutter. I want the notification to be a heads-up notification. After much research, on Android this is possible when the app is in the background, only by using, "data" when sending the notification, not "notification". So I send it like this:
"to": "/topics/all",
"data": {
"title": "Alert",
"body": "App maintanance is underway.",
}
and it works great.
However, I am also sending messages to ios devices. Now with iOS, the "notification" field has to be in the notification, otherwise the notification will not show up.
The problem is that when I add the "notification" field to the request, on Android the notification is shown up twice. Once due to "notification", and once because I manually display the notification as I customised, to make it pop up.
So when I send the message like this:
{
"to": "/topics/all",
"data": {
"title": "Alert",
"body": "App maintanance is underway.",
}
"notification": {
"title": "Alert",
"body": "App maintanance is underway.",
}
}
It comes into android twice.
Now I could make two topics, one for Android and one for iOS, but sometimes I send messages to specific devices with token, and I don't know if its an Android device or iOS.
How can I cater for both?
Thanks
Here is my flutter code:
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Inportance Notifications', // title
'This channel is used for important notifications.', // description
playSound: true,
importance: Importance.high,
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print('A message just showed up, id: ${message.messageId}');
showNotification(message); // without this it isn't heads-up when in background
}
Future<void> setUpFirebaseMessaging(BuildContext context) async {
print('2124: setUpFirebaseMessaging');
FirebaseMessaging.onBackgroundMessage(
_firebaseMessagingBackgroundHandler);
flutterLocalNotificationsPlugin.initialize;
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
// subscribe to topic on each app start-up
await FirebaseMessaging.instance.subscribeToTopic('all');
FirebaseMessaging.instance.getToken().then((value) {
String token = value;
print('2124: Firebase Token: ${token}');
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
// print('Message data: ${message.data}');
RemoteNotification notification = message.notification;
// AndroidNotification android = message.notification.android;
// AndroidNotification data = message.data;
// print('hashCode ${notification.hashCode}');
print('title ${message.data['title']}');
print('body ${message.data['body']}');
// if (notification != null) {
if (message.data != null) {
showNotification(message);
};
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published');
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification.android;
if(notification != null && android != null){
showDialog(context: context, builder: (_){
return AlertDialog(
title: Text(notification.title),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(notification.body)
],
),
),
);
});
}
});
}
void showNotification(RemoteMessage message) {
flutterLocalNotificationsPlugin.show(
message.hashCode,
message.data['title'],
message.data['body'],
// message.notification.title,
// message.notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channel.description,
color: Colors.blue,
playSound: true,
importance: Importance.max,
priority: Priority.high,
icon: '#drawable/ic_stat_output_onlinepngtools',
),
));
}
You should remove the showNotification function from _firebaseMessagingBackgroundHandler as it triggers its own notification (from local_notification package) and firebase messaging package has its own notification so we have two!!

FCM & Local notifications. Android works, on iOS not

Im using a solution with FCM and Local notifications to receive specific push notifications on a channel. Everything works for Android.
I send my push notifications trough Postman to https://fcm.googleapis.com/fcm/send and that all works pretty well.
However when I add my iPhone, and finished all the installation steps that were needed. The only thing I receive is the print in my console on flutter with the message. I don't receive any kind of notification on the iPhone itself.
final FirebaseMessaging _fcm = FirebaseMessaging();
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
var initializationSettingsAndroid;
var initializationSettingsIOS;
var initializationSettings;
void _showNotification() async {
//await _buildNotification();
}
Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) {
if (message.containsKey('data')) {
// Handle data message
final dynamic data = message['data'];
}
if (message.containsKey('notification')) {
// Handle notification message
final dynamic notification = message['notification'];
}
// Or do other work.
}
Future<void> _createNotificationChannel(
String id, String name, String description) async {
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
var androidNotificationChannel = AndroidNotificationChannel(
id,
name,
description,
importance: Importance.Max,
playSound: true,
sound: RawResourceAndroidNotificationSound('not_kiddin'),
enableVibration: true,
);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(androidNotificationChannel);
}
Future<void> _buildNotification(String title, String body) async {
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'my_channel',
'Channel Name',
'Channel Description.',
importance: Importance.Max,
priority: Priority.High,
playSound: true,
enableVibration: true,
sound: RawResourceAndroidNotificationSound('not_kiddin'),
ticker: 'noorderlicht');
var iOSChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, title, body, platformChannelSpecifics,
payload: 'payload');
}
#override
void initState() {
super.initState();
initializationSettingsAndroid =
AndroidInitializationSettings('ic_launcher');
initializationSettingsIOS = IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
_fcm.requestNotificationPermissions();
_fcm.configure(
onMessage: (Map<String, dynamic> message) async {
print(message);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
//_showNotification();
Map.from(message).map((key, value) {
print(key);
print(value);
print(value['title']);
_buildNotification(value['title'], value['body']);
});
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
},
);
}
Future onDidReceiveLocalNotification(
int id, String title, String body, String payload) async {
// display a dialog with the notification details, tap ok to go to another page
showDialog(
context: context,
builder: (BuildContext context) => CupertinoAlertDialog(
title: Text(title),
content: Text(body),
actions: [
CupertinoDialogAction(
isDefaultAction: true,
child: Text('Ok'),
onPressed: () {},
)
],
),
);
}
Future onSelectNotification(String payload) async {
if (payload != null) {
debugPrint('Notification payload: $payload');
}
}
_fcm.requestNotificationPermissions();
You need to request for permission in iOS (android dont need).
_fcm.requestNotificationPermissions(
const IosNotificationSettings(
sound: true, badge: true, alert: true, provisional: true));
FCM messages come in different structures for IOS, in your case remove the 'data' when the platform is IOS like these below.
if(Platform.isAndroid){
roomId = message['data']['chatRoomId'];
senderId = message['data']['senderId'];
}else if(Platform.isIOS){
roomId = message['chatRoomId'];
senderId = message['senderId'];
}

Categories

Resources