flutter: FCM count number of notifications
This is how I do it:
//define a global variable
ValueNotifier<int> notificationCounterValueNotifer =
ValueNotifier(0);
You can read about ValueNotifier
here.
Then when you receive a new notification, increase that value by 1:
_fcm.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
notificationCounterValueNotifer.value++;
notificationCounterValueNotifer.notifyListeners(); // notify listeners here so ValueListenableBuilder will build the widget.
// final snackbar = SnackBar(
// content: Text(message['notification']['title']),
// action: SnackBarAction(
// label: 'Go',
// onPressed: () => null,
// ),
// );
// Scaffold.of(context).showSnackBar(snackbar);
showDialog(
context: context,
builder: (context) => AlertDialog(
content: ListTile(
title: Text(message['notification']['title']),
subtitle: Text(message['notification']['body']),
),
actions: <Widget>[
FlatButton(
color: Colors.amber,
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
);
},
);
In order to notify listeners, you have to add ChangeNotifer
as a mixin to your class:
class _MessageHandlerState extends State<MessageHandler> with ChangeNotifier
You can choose a ValueListenableBuilder to build widgets whenever the value changes. so to update the badge, we use this widget:
ValueListenableBuilder(
builder: (BuildContext context, int newNotificationCounterValue, Widget child) {
// This builder will only get called when the notificationCounterValueNotifer is updated.
return Text(newNotificationCounterValue.toString()); //return your badge here
},
valueListenable: notificationCounterValueNotifer,
);
You can store the value in a database document and assign it at the start of your app so your notificationCounterValueNotifer
value is not 0.
If you want, you can set it to 0 again when you navigate to a notificationScreen
.
There might be better ways to do this but this is how I do it.
Update:
You need to return ValueListenableBuilder
from myAppBarIcon
:
Widget myAppBarIcon() {
//you have to return the widget from builder method.
//you can add logics inside your builder method. for example, if you don't want to show a badge when the value is 0.
return ValueListenableBuilder(
builder: (BuildContext context, int newNotificationCounterValue,
Widget child) {
//returns an empty container if the value is 0 and returns the Stack otherwise
return newNotificationCounterValue == 0? Container(): Stack(
children: [
Icon(
Icons.notifications,
color: Colors.white,
size: 30,
),
Container(
width: 30,
height: 30,
alignment: Alignment.topRight,
margin: EdgeInsets.only(top: 2),
child: Container(
width: 15,
height: 15,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(0xffc32c37),
border: Border.all(color: Colors.white, width: 1)),
child: Padding(
padding: const EdgeInsets.all(0.0),
child: Text(
newNotificationCounterValue.toString(),
),
),
),
),
],
);
},
valueListenable: notificationCounterValueNotifer,
);
}
Admin
Updated on December 24, 2022Comments
-
Admin over 1 year
I'm trying to create notification badge inside application (in home screen) on this code and I'm using Firebase Cloud Messaging with android app in flutter language, problem is I can't figure out how to count the number of received notification so
Any suggested way to count the number of received notifications from Firebase Cloud Messaging to android app?
PS: i have updated code now for the answer below and i'm still getting errors
// import 'package:flutter/foundation.dart'; // import 'package:flappy_search_bar/flappy_search_bar.dart'; import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:mycafe/main.dart'; import 'Custom_Text.dart'; import 'Pasta.dart'; import 'Burger.dart'; import 'Pizza.dart'; import 'AboutUs.dart'; import 'dart:async'; import 'ui/home/HomeScreen.dart'; import 'dart:math'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'ContactUs.dart'; import 'package:flutter/services.dart'; import 'package:mycafe/model/User.dart'; import 'package:mycafe/ui/home/HomeScreen.dart'; import 'package:mycafe/ui/services/Authenticate.dart'; import 'package:mycafe/ui/utils/helper.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'dart:async'; import 'dart:io'; import 'package:flushbar/flushbar.dart'; import 'package:flushbar/flushbar_helper.dart'; // import 'package:flutter/material.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'constants.dart' as Constants; import 'ui/auth/AuthScreen.dart'; import 'ui/onBoarding/OnBoardingScreen.dart'; import 'package:flutter/cupertino.dart'; import 'package:mycafe/ui/auth/AuthScreen.dart'; var bannerItems = ["Burger", "cheesechilly", "Noodles", "Pizza"]; var bannerImages = [ "images/burger.jpg", "images/cheesechilly.jpg", "images/noodles.jpg", "images/pizza.jpg" ]; ValueNotifier<int> notificationCounterValueNotifer = ValueNotifier(0); class Notify extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'FlutterBase', home: Scaffold( body: MessageHandler(), ), ); } } class MessageHandler extends StatefulWidget { @override _MessageHandlerState createState() => _MessageHandlerState(); } class _MessageHandlerState extends State<MessageHandler> with ChangeNotifier { final Firestore _db = Firestore.instance; final FirebaseMessaging _fcm = FirebaseMessaging(); StreamSubscription iosSubscription; @override void initState() { super.initState(); if (Platform.isIOS) { iosSubscription = _fcm.onIosSettingsRegistered.listen((data) { print(data); _saveDeviceToken(); }); _fcm.requestNotificationPermissions(IosNotificationSettings()); } else { _saveDeviceToken(); } // void _incrementCounter() { _fcm.configure( onMessage: (Map<String, dynamic> message) async { print("onMessage: $message"); // RaisedButton( // child: Text(message['notification']['title']), // onPressed: () { // Flushbar( // flushbarPosition: FlushbarPosition.TOP, // icon: Icon( // Icons.notifications_active, // color: Colors.white, // ), // mainButton: FlatButton( // onPressed: () { // Navigator.pop(context); // // Flush.showGoodFlushbar(context, 'login successful!'); // }, // // child: Text( // // "ADD", // // style: TextStyle(color: Colors.amber), // // ), // ), // // duration: Duration(seconds: 7)) // ).show(context); // }, // ); notificationCounterValueNotifer.value++; notificationCounterValueNotifer .notifyListeners(); // notify listeners here so ValueListenableBuilder will build the widget. final snackbar = SnackBar( content: Text(message['notification']['title']), action: SnackBarAction( label: 'Go', onPressed: () => null, ), ); Scaffold.of(context).showSnackBar(snackbar); // showDialog( // context: context, // builder: (context) => AlertDialog( // content: ListTile( // title: Text(message['notification']['title']), // subtitle: Text(message['notification']['body']), // ), // actions: <Widget>[ // FlatButton( // color: Colors.amber, // child: Text('Ok'), // onPressed: () => Navigator.of(context).pop(), // ), // ], // ), // ); }, onLaunch: (Map<String, dynamic> message) async { print("onLaunch: $message"); // TODO optional }, onResume: (Map<String, dynamic> message) async { print("onResume: $message"); // TODO optional }, ); } @override void dispose() { if (iosSubscription != null) iosSubscription.cancel(); super.dispose(); } @override Widget build(BuildContext context) { // _handleMessages(context); return MaterialApp(home: Scaffold(body: HomeApp())); } /// Get the token, save it to the database for current user _saveDeviceToken() async { // Get the current user String uid = 'jeffd23'; // FirebaseUser user = await _auth.currentUser(); // Get the token for this device String fcmToken = await _fcm.getToken(); // Save it to Firestore if (fcmToken != null) { var tokens = _db .collection('users') .document(uid) .collection('tokens') .document(fcmToken); await tokens.setData({ 'token': fcmToken, 'createdAt': FieldValue.serverTimestamp(), // optional 'platform': Platform.operatingSystem // optional }); } } /// Subscribe the user to a topic _subscribeToTopic() async { // Subscribe the user to a topic _fcm.subscribeToTopic('puppies'); } } Widget myAppBarIcon() { if (State is ValueNotifier) { return ValueListenableBuilder( builder: (BuildContext context, int newNotificationCounterValue, Widget child) { // return Container( // width: 50, // height: 10, child: Stack( children: [ Icon( Icons.notifications, color: Colors.white, size: 30, ), Container( width: 30, height: 30, alignment: Alignment.topRight, margin: EdgeInsets.only(top: 2), child: Container( width: 15, height: 15, decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xffc32c37), border: Border.all(color: Colors.white, width: 1)), child: Padding( padding: const EdgeInsets.all(0.0), child: Text( newNotificationCounterValue.toString(), ), ), ), ), ], ); //return your badge here }, valueListenable: notificationCounterValueNotifer, ); // return Container( // width: 50, // height: 10, // child: Stack( // children: [ // Icon( // Icons.notifications, // color: Colors.white, // size: 30, // ), // Container( // width: 30, // height: 30, // alignment: Alignment.topRight, // margin: EdgeInsets.only(top: 2), // child: Container( // width: 15, // height: 15, // decoration: BoxDecoration( // shape: BoxShape.circle, // color: Color(0xffc32c37), // border: Border.all(color: Colors.white, width: 1)), // child: Padding( // padding: const EdgeInsets.all(0.0), // child: Center( // child: ValueListenableBuilder(), // ), // ), // ), // ), // ], // ), // ); } else { return Container(); } } class HomeApp extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.deepOrange[900], title: Text('HuQQa BuzZ'), actions: <Widget>[myAppBarIcon()],