Reputation: 153
I already implemented the basic configuration suggested by the firebase_messaging flutter package. However, each time that I receive a notification on my flutter app onMessage is triggered twice. I'm using firebase_messaging 6.0.9, Dart 2.7.0 and Flutter 1.12.13+hotfix.5.
This is my [project]/android/build.gradle
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.google.gms:google-services:4.3.2'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
This is my [project]/android/app/build.gradle
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.chat_notification"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
apply plugin: 'com.google.gms.google-services'
And this is the code where the onMessage is triggered twice
import 'package:chat_notification/model/message.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
class MessageWidget extends StatefulWidget {
@override
_MessageWidgetState createState() => _MessageWidgetState();
}
class _MessageWidgetState extends State<MessageWidget> {
FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
List<Message> messages = [];
@override
void initState() {
// TODO: implement initState
super.initState();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> response) async {
print("onMessage: $response");
},
onLaunch: (Map<String, dynamic> response) async {
print("onLaunch: $response");
},
onResume: (Map<String, dynamic> response) async {
print("onResume: $response");
},
);
}
@override
Widget build(BuildContext context) => ListView(
children: messages.map(buildMessage).toList(),
);
Widget buildMessage(Message message) => ListTile(
title: Text(message.title),
subtitle: Text(message.body),
);
}
I already try creating new projects but it seems to happen for each of them. I would really appreciate if anyone can help me about this.
EDIT:
This is no longer present in latest version of firebase_messaging: 7.0.0. Best solution I found is updating the package. Duplicated messages are not longer present.
Upvotes: 14
Views: 11508
Reputation: 51
I faced this issue with firebase_messaging: 13.1.0 & firebase_core: 1.24.0
Temporary Solution,
String newMessageId = '';
FirebaseMessaging.onMessage.listen((RemoteMessage? message) {
if (message!.messageId != newMessageId) showSimpleNotification(message);
newMessageId = message.messageId!;
});`
Upvotes: 4
Reputation: 622
I faced this issue with firebase_messaging: ^10.0.4
Going through literature, I see that this is a bug that keeps occurring every now and then across versions.
Knowing that, I personally wouldn't use the methods mentioned in the answer (using a boolean flag, odd/even flag).
I got around the issue by using a time controlled semaphore.
static int semaphore = 0;
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
if (semaphore != 0) {
return;
}
semaphore = 1;
Future.delayed(Duration).then((_) => semaphore = 0);
handleMessage(message);
});
Also avoids concurrent remote message launches (based on the Duration you pass) - though I can't imagine a real world situation where remote messages might be launched concurrently.
Upvotes: 4
Reputation: 109
Update:
This is no longer present in latest version of firebase_messaging (7.0.0 or up). Best solution I found is updating the package. Duplicated messages are not longer present.
Original Solution:
I am facing the same problem. I don't know the reason or the solution for it. A simple way-around is using a even odd counter to catch only one of the two callbacks.
import 'package:chat_notification/model/message.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
class MessageWidget extends StatefulWidget {
@override
_MessageWidgetState createState() => _MessageWidgetState();
}
class _MessageWidgetState extends State<MessageWidget> {
FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
List<Message> messages = [];
static int i = 0;
@override
void initState() {
// TODO: implement initState
super.initState();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> response) async {
if(i%2==0) {
print("onMessage: $response");
// something else you wanna execute
};
i++;
},
onLaunch: (Map<String, dynamic> response) async {
print("onLaunch: $response");
},
onResume: (Map<String, dynamic> response) async {
print("onResume: $response");
},
);
}
@override
Widget build(BuildContext context) => ListView(
children: messages.map(buildMessage).toList(),
);
Widget buildMessage(Message message) => ListTile(
title: Text(message.title),
subtitle: Text(message.body),
);
}
This will run the code only once! Can be used for onLaunch and onResume similarly.
Upvotes: 9
Reputation: 3041
Update to latest FireFlutter package solve this issue:
For non-null safety:
firebase_messaging: ^8.0.0-dev.15
firebase_core: ^0.7.0
Upvotes: 0
Reputation: 7462
I had this same issue and what caused it was that I had recently renamed my project. I noticed (after too long) that one of the notification banners said the old app name and one said the new app name. After uninstalling and then reinstalling the app (along with flutter clean
), the double notifications went away.
In short, if nothing else works, try uninstalling and reinstalling your app again.
Upvotes: 0
Reputation: 1
This is the perfect code for this issue. Just we need to do is to declare a static bool variable, It will work with onResume(). Before only some logic is missing, that's why it is calling twice. Now, It is working for me. Hope, you will also get help from this.
onMessage: // ignore: missing_return (Map<String, dynamic> msg) { if(!isNotified) { print("onMessage called"); print(msg); DocumentReference documentReference = Firestore.instance.collection('PushNotifications').document(); documentReference.setData({ "payload": msg }); } isNotified = !isNotified; }
Upvotes: 0