After carefully trying other answer, nothing seems to work.
Notification are working fine, when I click on them and the app has been initialised.
When the app is closed or terminated it is impossible for me to redirect the user to a page because the value of the getInitialMessage() is null.
For example, this return null, but it is the home page of my Flutter app
#override
void initState() {
super.initState();
FirebaseMessaging.instance
.getInitialMessage()
.then((message) => print('Initial message: $message'))
Main.dart
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
runApp(const FrontDeskApp());
}
Thank you
This may be the reason because you are using getInitialMessage() method in wrong way.
Modify your main.dart like the below way and test.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
await FirebaseMessaging.instance.getInitialMessage().then((remoteMessage) {
// whenever you open the app from the terminate state by clicking on Notification message,
here you will get your remoteMessage.
// Set you App Screen Redirection here.
// Once consumed, the RemoteMessage will be removed.
});
runApp(const MyApp());
}
For more reference please refer to the official document for Handling Interaction of Notification
Related
I am making an app with flutter. I want to store data after 24 hours and update UI in app.
I try with Timer.periodic() but it does not count the time when app is close. It only works when the application is open.
Is it possible to execute a function after a specific time even if the app is closed?
Here is my current code:
void callbackDispatcher() async{
Workmanager().executeTask((task, inputData) {
switch(sdDaily){
case 'StoreDataDaily':
storeData.storeDailyData();
break;
default:
}
return Future.value(true);
});
}
void main() async{
WidgetsFlutterBinding.ensureInitialized();
Directory directory = await path_provider.getApplicationDocumentsDirectory();
print(directory.path);
Hive.init(directory.path);
await Hive.initFlutter(directory.path);
Hive.registerAdapter(UserAdapter());
Hive.registerAdapter(WaterAdapter());
Hive.registerAdapter(WeekAdapter());
Get.put(UserController());
Get.put(WaterController());
await Hive.openBox<User>('data');
await Hive.openBox<Water>('water_data');
await Hive.openBox<Week>('week_data');
await notificationPlugin.showNotification();
await Workmanager().initialize(callbackDispatcher, isInDebugMode: true);
var uniqueId = DateTime.now().second.toString();
var userBox = Hive.box<User>('data');
if(userBox.get(0)?.status == 1){
await Workmanager().registerOneOffTask(uniqueId, sdDaily,);
}
runApp(const MyApp());
}
You can use : flutter_background_service. to execute background services and it'll also help you sending a custom notification when you are actually going to store that data later.
You can use firebase cloud funcitons to do schedule tasks or whatever you want to do even if app is closed or killed.
i listen to the notification as below
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await FirebaseMessaging.instance.getToken();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(MyProject(
appRouter: AppRouting(),
));
}
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();
NotificationServices ntService = NotificationServices();
print("Handling a background message: ${message.data['room']}");
ntService.showNotification(message);
}
void showNotification(RemoteMessage message) {
flutterLocalNotificationsPlugin.show(
message.data.hashCode,
message.data['title'],
message.data['body'],
NotificationDetails(
android: AndroidNotificationDetails(
NotificationServices.channel.id,
NotificationServices.channel.name,
channelDescription: NotificationServices.channel.description,
//channel.description,
icon: 'launch_background',
playSound: true,
// other properties...
),
),
payload: message.data['room']);
}
}
await flutterLocalNotificationsPlugin.initialize(
initialzationSettings,
onDidReceiveNotificationResponse: onSelectNotification,
onDidReceiveBackgroundNotificationResponse: onSelectNotification,
);
in the onSelectNotification
i get the roomID and then navigate to it but to do so i had to but it in the homepage screen in order to set the user and room data so i get an error i should use in the top level function in the main.dart and it is working fine with the foreground notification but for the background it just open the app so any ideas of how should i do it
I assumed I followed all the steps to handling background notifications from firebase in flutter. I have created a top-level function that I am expecting to be triggered whenever a notification comes in. However, the function is never triggered.
Here's the top-level background handler function that exists in my home page widget but outside the class:
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
// ignore: avoid_print
print('A background message just showed up : ${message.messageId}');
// update SQLite
var result = await PageService.instance
.add(PageService.instance.convertToPage(message.data));
print('added to db: ${result}');
}
Here is my home page init state that calls a function to initialize firebase messgaging:
#override
void initState() {
super.initState();
_initializeFirebaseMessaging();
}
And then here is the _initializeFirebaseMessaging function that is defined in the home page class as well:
void _initializeFirebaseMessaging() {
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
print('new notification arrived');
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
// update SQLite
var result = await PageService.instance
.add(PageService.instance.convertToPage(message.data));
print('added to db: ${result}');
if (notification != null && android != null) {
// show notification
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
color: Colors.blue,
playSound: true,
icon: '#mipmap/ic_launcher',
),
));
}
});
}
The onmessage.listen works fine as I get notificationd and handle them while I'm in the app, but the background handler is not triggered at all.
I would appreciate any help!
You have to call FirebaseMessaging.onBackgroundMessage inside your main() not in initState()
try: after main func
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
...
}
and remove WidgetsFlutterBinding.ensureInitialized(); in firebaseMessagingBackgroundHandler
onMessage handles foreground notification
onMessageOpenedApp handles background notification
Instead of using onMessage for handling Background notifications, add another function block of FirebaseMessaging with onMessageOpenedApp, if you want notification while the app is in background, like this:
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message){...})
onMessage only works when the app is in foreground.
If you want notification while the app is in the terminated state you can use:
FirebaseMessaging.instance.getInitialMessage().then((message){...})
Update your firebaseMessagingBackgroundHandler to this:
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
// ignore: avoid_print
print('A background message just showed up : ${message.messageId}');
// update SQLite
var result = await PageService.instance
.add(PageService.instance.convertToPage(message.data));
print('added to db: ${result}');
}
And finally, the main() should look like this:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// Add Firebase Initialization:
await Firebase.initializeApp();
// This will initialize a new Firebase instance.
// Background message handler
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
runApp(const App());
}
You should call FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); from within main(), not from Homepage initState(){}.
I'm trying to navigate user when user tap the notification.
It is working as I want but one situation(application is not opened), I mean application is not on the background, it is completely closed. User tap the notification and application firstly see the splash sceren after that load some initial news on initial page and do not navigating. I tried to add some delay but not worked. How can I fix this?
My main function
main() async {
WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
setupLocator();
await Hive.initFlutter();
Hive.registerAdapter(UserDataAdapter());
await Hive.openBox<UserData>('userData');
await dotenv.load();
await GetStorage.init();
Get.put(MainController());
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
runApp(const MyApp());
}
Running notification tap function when user click the notification
Future<void> onTapNotification(RemoteMessage message) async {
log('Notification tapped', name: 'TAP NOTIFICATION');
inspect(message);
Get.toNamed(
'/notification-news',
parameters: {
"news_id": message.data['news_id'],
},
);
}
I am coming from an old Firebase_messaging plugin 6 + to the newer Firebase_messenger plugin 10 +, I am able to do most of the thing but can't get the message data, I want to convert this code from the older plugin to a newer one and use methods like configure launch and onResume.I can receive the push notifications, foreground and background information about the message but can't read it.
class _ChatScreenState extends State<ChatScreen> {
#override
void initState() {
super.initState();
final fbm = FirebaseMessaging();
fbm.requestNotificationPermissions();
fbm.configure(onMessage: (msg) {
print(msg);
return;
}, onLaunch: (msg) {
print(msg);
return;
}, onResume: (msg) {
print(msg);
return;
});
}
What I have done so far
Under AndroidManifest.xml added
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="high_importance_channel" />
On main.dart
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print('Handling a background message ${message.messageId}');
}
Future <void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(MyApp());
}
Here is where I want to get the data from the server
class _ChatScreenState extends State<ChatScreen> {
#override
void initState() {
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
if (message != null) {
print(message);
}
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
print('Message data: ${message.data}');
if (message.notification != null) {
print(
'Message also contained a notification: ${message.notification}');
}
});
});
super.initState();
}
On Debug while the App is in the foreground
D/FLTFireMsgReceiver(15437): broadcast received for message
I/flutter (15437): Got a message whilst in the foreground!
I/flutter (15437): Message data: {}
I/flutter (15437): Message also contained a notification: Instance of 'RemoteNotification'
On Background
D/FLTFireMsgReceiver(15437): broadcast received for message
W/FirebaseMessaging(15437): Missing Default Notification Channel metadata in AndroidManifest. Default value will be used.
I/flutter (15437): Handling a background message 0:1624718321445677%ba7e1d8bba7e1d8b
Although the Notification Text and body is fine in the notification window but can't get the same info in the debug screen, it returns empty. Also is my implementation correct?
With a little bit of searching I believe the missing piece was flutter_local_notifications: ^5.0.0+4 The changes I have made in
main.dart
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();
print('Handling a background message ${message.messageId}');
}
const AndroidNotificationChannel channel = const AndroidNotificationChannel(
//for notificaiton initialization
'high_importance_channel', // id
'High Importance Notifications', // title
'This channel is used for important notifications.', // description
importance: Importance.high,
playSound: true,
);
//initialize plugin
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
//for background messaging
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
//Local Notification implementation
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
//for firebase plugin and messaging required
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
runApp(MyApp());
}
In the class where I want the notification
class _ChatScreenState extends State<ChatScreen> {
#override
void initState() {
//foreground messaging
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message
.notification; //assign two variables for remotenotification and android notification
AndroidNotification android = message.notification?.android;
if (notification != null && android != null) {
print(message);
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id, channel.name, channel.description,
color: Colors.blue,
playSound: true,
icon: '#mipmap/ic_launcher'),
),
);
print(notification.title);
print(notification.body);
}
});
//Do when the user taps the notification
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
//same as above
});
super.initState();
}
Would be nice if some one update this process for IOS as I don't have a developer Id to test it.