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'];
}
Related
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());
}
I'm working on a Flutter App with Firebase Messaging. The notifications work perfectly fine on iOS. On Android, they work when the app is in the foreground, but are not displayed when the app is in background or terminated. I could already rule out doze mode, as the app has been put to background just seconds before triggering the message. The logfile also says, the message is received by the devices, but somehow not displayed.
The problem also only exists when the app is installed via .apk and not when I build directly with Android Studio, so I thought maybe the fingerprinting could cause the problem. But the messages are received by the device and just not displayed -> so that's not it either, right?
I use firebase_messaging: ^12.0.0 as the plugin.
Here is the implementation of my background handler:
static Future<void> setUp() async {
await Firebase.initializeApp(
name: 'Firebase-App',
options: DefaultFirebaseOptions.currentPlatform,
);
//... iOS stuff
//Enable Foreground-Messages for Android
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description:
'This channel is used for important notifications.', // description
importance: Importance.max,
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await configLocalNotification(flutterLocalNotificationsPlugin);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
//Display Foreground-Message on Android
flutterLocalNotificationsPlugin.show(
message.hashCode,
Uri.decodeComponent(message.data['title']).replaceAll('+', ' '),
Uri.decodeComponent(message.data['message']).replaceAll('+', ' '),
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
icon: '#mipmap/ic_launcher',
importance: Importance.max,
),
),
payload: json.encode(message.data),
);
});
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
}
static Future<void> _firebaseMessagingBackgroundHandler(
RemoteMessage message) async {
await Firebase.initializeApp();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description:
'This channel is used for important notifications.', // description
importance: Importance.max,
);
await flutterLocalNotificationsPlugin.show(
message.hashCode,
Uri.decodeComponent(message.data['title']).replaceAll('+', ' '),
Uri.decodeComponent(message.data['message']).replaceAll('+', ' '),
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
icon: '#mipmap/ic_launcher',
importance: Importance.max,
// other properties...
),
),
payload: json.encode(message.data),
);
}
static Future<void> configLocalNotification(
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin) async {
const initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
const initializationSettingsIOS = IOSInitializationSettings();
const initializationSettings = InitializationSettings(
iOS: initializationSettingsIOS, android: initializationSettingsAndroid);
//Handle on click event when App is in foreground or background
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
//handle on click event when app is terminated
final NotificationAppLaunchDetails? notificationAppLaunchDetails =
await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) {
final String? selectedNotificationPayload =
notificationAppLaunchDetails!.payload;
debugPrint(
'notification payload on launch: $selectedNotificationPayload');
await onSelectNotification(selectedNotificationPayload);
}
}
Thanks in advance for your help, I'm really at the end of the line here!
I want the notification to display on particular time which end-user selects it using time picker. i'm confused with the process of how to do that. please guide me to solve this problem.
Getting variable from model:
late var selectedTime = TimeOfDay.now();
User picks the time from front-end:
Future<Null> selectTime (BuildContext context) async{
picked = (await showTimePicker(
context: context,
initialTime: model.selectedTime,
))!;
if (picked != null){
setState(() {
model.selectedTime = picked;
this.preferences?.setString("dateValue", model.selectedTime.format(context));
});
}
}
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
child: GestureDetector(
onTap: (){
selectTime(context);
},
child: Text(
'${this.preferences?.getString("dateValue") ?? model.defaultTime.format(context)}',
),
),
This class contains notifications sepearately.
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
final mymodel = myModel();
Future<void> firstNotifications() async{
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
const AndroidNotificationDetails firstNotificationSpecifics =
AndroidNotificationDetails(
'channel id',
'channel name',
'channel description',
sound: RawResourceAndroidNotificationSound('song1'),
playSound: true,
enableVibration: false ,
visibility: NotificationVisibility.secret,
autoCancel: true,
timeoutAfter:7000
);
const NotificationDetails firstNotificationPlatformSpecifics =
NotificationDetails(android: firstNotificationSpecifics);
await flutterLocalNotificationsPlugin.zonedSchedule
(1, null, null, tz.TZDateTime.now(tz.local).add(Duration(seconds: 5)), firstNotificationPlatformSpecifics,
uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
androidAllowWhileIdle: true);
}
But now this code play notification after 5 seconds which i had given manually. but i want the notification to display at the user picked time.
You need to call the setNotification function after you picked the time
Future<Null> selectTime (BuildContext context) async{
picked = (await showTimePicker(
context: context,
initialTime: model.selectedTime,
))!;
if (picked != null){
setState(() {
model.selectedTime = picked;
setNotification(picked);//Call it here
this.preferences?.setString("dateValue", model.selectedTime.format(context));
});
}
}
void setNotification( TimeOfDay selectedTime) {
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
// final mymodel = myModel();
Future<void> firstNotifications() async {
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
const AndroidNotificationDetails firstNotificationSpecifics =
AndroidNotificationDetails(
'channel id', 'channel name', 'channel description',
sound: RawResourceAndroidNotificationSound('song1'),
playSound: true,
enableVibration: false,
visibility: NotificationVisibility.secret,
autoCancel: true,
timeoutAfter: 7000);
const NotificationDetails firstNotificationPlatformSpecifics =
NotificationDetails(android: firstNotificationSpecifics);
tz.TZDateTime zonedTime = tz.TZDateTime.local(DateTime.now().year,DateTime.now().month,DateTime.now().day,selectedTime.hour,
selectedTime.minute).subtract(DateTime.now().timeZoneOffset);
await flutterLocalNotificationsPlugin.zonedSchedule(
1,
null,
null,
tz.TZDateTime.now(tz.local) ,
firstNotificationPlatformSpecifics,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
androidAllowWhileIdle: true);
}
}
I have built my own application in flutter and I have implemented Local notifications and also FirebaseMessaging:
final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
#override
void initState() {
super.initState();
registerNotification();
configLocalNotification();
firebaseMessaging.requestNotificationPermissions();
}
void registerNotification() {
firebaseMessaging.requestNotificationPermissions();
firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
print('onMessage: $message');
Platform.isAndroid
? showNotification(message['notification'])
: showNotification(message['aps']['alert']);
return ;
}, onResume: (Map<String, dynamic> message) {
print('onResume: $message');
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NotificationsScreen()));
}, onLaunch: (Map<String, dynamic> message) {
print('onLaunch: $message');
return;
});
firebaseMessaging.getToken().then((token) {
print('token: $token');
FirebaseFirestore.instance
.collection('Consultant')
.doc(firebaseUser.uid)
.update({'deviceToken': token});
}).catchError((err) {
//Fluttertoast.showToast(msg: err.message.toString());
});
}
Future selectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
await Navigator.push(
context,
MaterialPageRoute<void>(builder: (context) => NotificationsScreen(payload: payload,)),
);
}
void showNotification(message) async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
Platform.isAndroid
? 'it.wytex.vibeland_pro_app'
: 'it.wytex.vibeland_pro_app',
'Vibeland',
'Vibeland',
playSound: true,
enableVibration: true,
importance: Importance.max,
priority: Priority.high,
ongoing: true,
);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iOSPlatformChannelSpecifics);
print(message);
print(message['body'].toString());
print(json.encode(message));
await flutterLocalNotificationsPlugin.show(0, message['title'].toString(),
message['body'].toString(), platformChannelSpecifics,
payload: json.encode(message));
await flutterLocalNotificationsPlugin.show(
0, '📩 Hai ricevuto un messaggio 📩 ', 'Controlla subito le Tue notifiche 🔔🔔', platformChannelSpecifics,
payload: 'item x',
);
}
void configLocalNotification() {
var initializationSettingsAndroid =
new AndroidInitializationSettings('vibeland_pro');
var initializationSettingsIOS = new IOSInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
var initializationSettings = new InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
I wrote a function into index.js to push also firestore notification when user creates order etc..
Everything works fine, I got Localnotifications when all is open and FCM notifications when app is in background, the problem is when the app sleep...
after some minutes the app goes in sleep mode and to start it again you need to restart the application which keep my user Logged:
MultiProvider(
providers: [
Provider<AuthenticationProvider>(
create: (_) => AuthenticationProvider(FirebaseAuth.instance),
),
StreamProvider(
create: (context) => context.read<AuthenticationProvider>().authState,
)
],
child: MaterialApp(
theme: ThemeData(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(
),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
}
)
),
debugShowCheckedModeBanner: false,
title: 'Vibeland Admin Authentication',
home: Authenticate(),
),
);
}
}
class Authenticate extends StatelessWidget {
#override
Widget build(BuildContext context) {
final firebaseUser = context.watch<User>();
if (firebaseUser != null) {
return StartScreenLogged();
}
return StartScreen();
}
}
but if I dont run again the app I dont get the notification because the app sleep.
what we need to do in this case?
I want my flutter app to open a page when a local notification is clicked. I've defined the following codes in the event listener:
Navigator.push(
Ccontext,
MaterialPageRoute(builder: (context) => PendingOrders()),
);
debugPrint('notification payload: ' + payload);
The event listener is executed successfully and printed the debugPrint's parameter when a local notification is called but it can not open the PendingOrders route.
Here is the full code in the main.dart
class _MyAppState extends State<MyApp> {
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
#override
void initState() {
super.initState();
var android = AndroidInitializationSettings('mipmap/ic_launcher');
var ios = IOSInitializationSettings();
var platform = InitializationSettings(android, ios);
flutterLocalNotificationsPlugin.initialize(platform,onSelectNotification: onSelectNotification);
_firebaseMessaging.subscribeToTopic('order-created');
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
showNotification(message);
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
print("Hafijur");
},
onResume: (Map<String, dynamic> message) async {
print("onResume: ${message['notification']['data']['click_action']}");
},
);
_firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(sound: true, badge: true, alert: true));
}
showNotification(Map<String, dynamic> msg) async {
var android = new AndroidNotificationDetails(
'sdffds dsffds',
"CHANNLE NAME",
"channelDescription",
);
var iOS = new IOSNotificationDetails();
var platform = new NotificationDetails(android, iOS);
await flutterLocalNotificationsPlugin.show(
0, "New order arrived", "Hey, hurry up! you have a order to deliver", platform,payload: "order created");
}
Future onSelectNotification(String payload) async {
this.build(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PendingOrders()),
);
if (payload != null) {
debugPrint('notification payload: ' + payload);
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: Constants.lightTheme,
debugShowCheckedModeBanner: false,
routes: {
"/": (context) => MainScreen(),
"/login": (context) => LoginPage(),
"/dashboard": (context) => Dashboard(),
"/all_orders": (context) => AllOrders(),
"/pending_orders": (context) => PendingOrders(),
"/delivered_orders": (context) => DeliveredOrders(),
"/order": (context) => Order(),
},
);
}
}
To receive payload when app was closed after open with tapping on notification then you have to use getNotificationAppLaunchDetails method
final NotificationAppLaunchDetails? notificationAppLaunchDetails =
await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
String? payload = notificationAppLaunchDetails!.payload;
put this code in main after notification initialization lines
use onSelectNotification will be triggered only if the app is already open when tapping notification.
but if the app is already closed and you want to run it after tapping notification with handling the payload value then you have to use getNotificationAppLaunchDetails
code will be something like following:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOs = IOSInitializationSettings();
var initSetttings = InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOs);
var cnf = await flutterLocalNotificationsPlugin.initialize(initSetttings,
onSelectNotification: onSelectNotification);
final NotificationAppLaunchDetails? notificationAppLaunchDetails =
await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
print('payload=');
String? payload= notificationAppLaunchDetails!.payload;
print(payload);
runApp(
MaterialApp(
home: payload== 'page1' ? Page1() : MainPage()
)
);
}
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
var initializationSettingsAndroid =
const AndroidInitializationSettings('#drawable/icon_menu_car_no');
var initializationSettingsIOs = const IOSInitializationSettings();
var initSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOs);
flutterLocalNotificationsPlugin?.initialize(initSettings,
onSelectNotification: (payload) {
switch(payload){
case "A":
//route to some where
break;
}
});
FirebaseMessaging.onMessage.listen((message) async {
showNotification(message);
});
void showNotification(RemoteMessage message) {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
var messageData = FirebaseMessageObject.fromJson(message.data);
flutterLocalNotificationsPlugin?.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel!.id,
channel!.name,
channelDescription: channel!.description,
icon: 'icon_menu_car_no',
),
),
payload: messageData.functionID);
}
}
class FirebaseMessageObject{
late String functionID;
static FirebaseMessageObject fromJson(Map<String,dynamic> data){
FirebaseMessageObject object = FirebaseMessageObject();
object.functionID = data['functionID'];
return object;
}
}
※FCM Request
{
"to": "your fcm token ",
"notification": {
"body": "I am body ",
"title": "I am title ",
"sound": "default"
},
"data":{
"functionID":"A"
},
"priority": "high"
}
I had a similar issue but this fixed my problem
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) {
displayNotification(message);
return;
},
onResume: (Map<String, dynamic> message) {
_navigateToItemDetail(message);
return;
},
onLaunch: (Map<String, dynamic> message) {
_navigateToItemDetail(message);
return;
},
);
void _navigateToItemDetail(Map<String, dynamic> message) async {
Navigator.popUntil(context, (Route<dynamic> route) => route is PageRoute);
await Navigator.of(context).push(PageRouteBuilder(
opaque: false, pageBuilder: (context, _, __) => NewPage();
}