`I am developing a Flutter app where I am using Firebase Cloud Messaging (FCM) to receive notifications. The badge count updates and resets correctly when the app is in the foreground, but when the app is in the background or closed, the badge count increments as expected but does not reset.
I implemented the badge count functionality using SharedPreferences to persist the count and a method to reset it when necessary. I expect the badge count to reset when the app is reopened after being in the background or closed. While the app is active, the count updates as expected, but after the app goes into the background or is closed and then reopened, it fails to reset and continues from the previous value.`
Here is my implementation:
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
if (message.notification != null) {
NotificationApi().showNotification(message);
BadgeCounter.incrementBadgeCount();
}
}
class NotificationApi {
Future initNotifications() async {
// Other initialization code
await initPushNotifications();
}
Future<void> initPushNotifications() async {
FirebaseMessaging.instance.getInitialMessage().then(_handleMessage);
FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
FirebaseMessaging.onBackgroundMessage(_handleBackgroundMessage);
FirebaseMessaging.onMessage.listen((message) {
debugPrint('onMessage: ${BadgeCounter.badgeNotifier.value}');
BadgeCounter.incrementBadgeCount();
showNotification(message);
});
}
}
class BadgeCounter {
static ValueNotifier<int> badgeNotifier = ValueNotifier<int>(0);
static const String keyBadgeCount = 'keyBadgeCount';
static Future<void> loadBadgeCount() async {
final prefs = await SharedPreferences.getInstance();
prefs.reload();
badgeNotifier.value = prefs.getInt(keyBadgeCount) ?? 0;
}
static Future<void> incrementBadgeCount() async {
final prefs = await SharedPreferences.getInstance();
prefs.reload();
badgeNotifier.value++;
await prefs.setInt(keyBadgeCount, badgeNotifier.value);
}
static Future<void> resetBadgeCount() async {
final prefs = await SharedPreferences.getInstance();
badgeNotifier.value = 0;
await prefs.setInt(keyBadgeCount, badgeNotifier.value);
}
}
class _HomeViewState extends ConsumerState<HomeView> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
NotificationApi().initNotifications();
BadgeCounter.loadBadgeCount();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed) {
debugPrint('AppLifecycleState.resumed');
SharedPreferences.getInstance().then((prefs) => {
prefs.reload().then((_) {
BadgeCounter.loadBadgeCount();
})
});
}
}
@override
void dispose() {
super.dispose();
WidgetsBinding.instance.removeObserver(this);
}
}
class _NotificationViewState extends ConsumerState<NotificationView> {
@override
void initState() {
super.initState();
BadgeCounter.resetBadgeCount();
}
}
hkrtl is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
if (message.notification != null) {
BadgeCounter.incrementBadgeCount();
NotificationApi().showNotification(message);
}
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Badge Notification',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomeView(),
);
}
}
class BadgeCounter {
static ValueNotifier<int> badgeNotifier = ValueNotifier<int>(0);
static const String keyBadgeCount = 'keyBadgeCount';
static Future<void> loadBadgeCount() async {
final prefs = await SharedPreferences.getInstance();
badgeNotifier.value = prefs.getInt(keyBadgeCount) ?? 0;
}
static Future<void> incrementBadgeCount() async {
final prefs = await SharedPreferences.getInstance();
int currentCount = prefs.getInt(keyBadgeCount) ?? 0;
currentCount++;
await prefs.setInt(keyBadgeCount, currentCount);
badgeNotifier.value = currentCount;
}
static Future<void> resetBadgeCount() async {
final prefs = await SharedPreferences.getInstance();
badgeNotifier.value = 0;
await prefs.setInt(keyBadgeCount, badgeNotifier.value);
}
}
class NotificationApi {
Future<void> initNotifications() async {
await initPushNotifications();
}
Future<void> initPushNotifications() async {
FirebaseMessaging.instance.getInitialMessage().then(_handleMessage);
FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
FirebaseMessaging.onMessage.listen((message) {
BadgeCounter.incrementBadgeCount();
showNotification(message);
});
}
void _handleMessage(RemoteMessage? message) {
if (message != null) {
showNotification(message);
}
}
void showNotification(RemoteMessage message) {
debugPrint('Notification: ${message.notification?.title ?? 'No Title'}');
}
}
class HomeView extends ConsumerStatefulWidget {
@override
_HomeViewState createState() => _HomeViewState();
}
class _HomeViewState extends ConsumerState<HomeView> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
NotificationApi().initNotifications();
BadgeCounter.loadBadgeCount();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed) {
BadgeCounter.loadBadgeCount();
}
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home View'),
),
body: Center(
child: ValueListenableBuilder<int>(
valueListenable: BadgeCounter.badgeNotifier,
builder: (context, badgeCount, _) {
return Text('Badge Count: $badgeCount');
},
),
),
);
}
}
class NotificationView extends ConsumerStatefulWidget {
@override
_NotificationViewState createState() => _NotificationViewState();
}
class _NotificationViewState extends ConsumerState<NotificationView> {
@override
void initState() {
super.initState();
BadgeCounter.resetBadgeCount();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Notification View'),
),
body: Center(
child: Text('Notifications'),
),
);
}
}
Javroid Breakers is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.