-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[firebase_messaging]: onMessage listener fires twice on iOS18 devices #13366
Comments
I'm having the same problem. [Environment] |
Hello, Is it working fine in the android application? Can you tell me? |
On Android it is working as expected. @soumyajitdas365 |
@soumyajitdas365 |
Can you help by providing the code for Android? |
I have faced the same issue today after upgrading to iOS 18. |
Please refer to the official documentation https://firebase.google.com/docs/flutter/setup?platform=android |
Thanks for the insight. I will test that myself. |
Yes indeed in my function log i also see that the notification is sent once and i have tried to sent it from my local machine using the firebase admin sdk, it doesn't send 2 notifications server-side. Besides, the client listener is only fired once on my android device using and on my iOS 17.5.1 device it fires only once the client listener 🙏🏻 |
Same problem here. I upgraded to Xcode 16.0 and iOS18 and now the onMessage listener fires twice every time a message is received. |
Same problem, I would like to know which version is available for the current situation? |
Same problem here, I wish I found this earlier because I was struggling for 13 hours thinking the problem in my code. |
Since this is only happening when the app is in foreground, it would be better to save the message ids to an array at runtime. This way you can check whether the corresponding message id is already existing in the array and thus already been processed. Then you can just ignore any further messages with the same id. |
Hi @justChris , thanks for submitting this issue. I'm going to upgrade my iOS to version 18 since it's prerequisite to reproduce this issue. I'd provide feedback on my findings. |
Also facing the same issue. Did some tests from my side. Flutter version: Firebase dependencies: firebase_core: 3.3.0 Devices Tested: iOS 18.0 (iPhone 15 Pro): Messaging received twice when app is in the foreground. |
Hi @justChris , I'm able to reproduce this issue on iOS 18. |
Hi guys, we have the same issue. We are receiving on iOS 18 devices events onMessage twice. On iOS 17 device with the same code base it is only fired once. Very critical bug. |
Yes, I think it's the best way to deal with the bug until we get a fixed version of Firebase lib. final _recievedMessages = <String>[];
void _onMessageHandler(RemoteMessage message) {
final messageId = message.messageId;
if (_recievedMessages.contains(messageId)) {
return;
}
if (messageId != null) {
_recievedMessages.add(messageId);
}
// your message handle logic here
}
StreamSubscription? _onMessageSubscription;
_onMessageSubscription ??= FirebaseMessaging.onMessage.listen(_onMessageHandler); |
For me onMessage.listen is not invoked, it's a really big issue on IOS18 |
Hello all, we are investigating this issue, but it seems to be a bug in iOS 18 not directly related to FlutterFire: https://forums.developer.apple.com/forums/thread/761597 |
+1 |
Are there any news on that by now? |
This bug made me think I lost my mind, any updates on the fix? |
Me too, please help, almost lost my job |
Was having the same issue, after updating to iOS 18.1 on device the issue stopped. Given iOS 18.0 will be around for a while we've put in a check to save the message id's and not show any duplicates. |
Unfortunately I tried with iOS 18.1 and the bug persists |
This is how I solved it temporarily. I hope the official will optimize it as soon as possible.
|
This is how I solved it temporarily. I hope the official will optimize it as soon as possible.
|
Yes, I also solved it as per the suggestion: #13366 (comment) |
Also messages without title and body ( silent notifications ) never received at ios 18. And those with title and body fired twice. |
@niosme data-only notifications work for me on iOS 18 with the following configuration:
Adding the Here is a 1-second silent audio file in the correct format. Just drag and drop it into your project in Xcode and add to the target when prompted: silent.caf.zip. Then set the Snippet from Apple APN Payload Key Reference:
Also see https://stackoverflow.com/questions/19239737/silent-push-notification-in-ios-7-does-not-work/ |
I just tryed that and doesnt work. I use this code in php to send a notification and it was working fine before the update. use \Kreait\Firebase\Factory as FirebaseFactory;
use \Kreait\Firebase\Messaging\CloudMessage as FirebaseCloudMessage;
use \Kreait\Firebase\Exception\MessagingException as FirebaseMessagingException;
/**
* helper.
*
* @since 1.0.0
*/
class FirebaseHelper
{
private $messaging;
private $isFirebaseInitialized = false;
private $errorMessage = '';
/**
* Constructor. Initializes the Firebase messaging service.
*
* Requires the `kreait/firebase-php` library installed via composer.
* Expects a `firebase_config.json` file in the component's administrator assets folder.
*
* @return void
*/
function __construct() {
require_once JPATH_ROOT.'/administrator/components/com_myapp/assets/firebase/firebase_library/vendor/autoload.php';// Include the Firebase PHP library
$firebase_config_path = JPATH_ROOT.'/administrator/components/com_myapp/assets/firebase/firebase_config.json';
if (!file_exists($firebase_config_path)) { $this->errorMessage = "Firebase configuration file not found."; return; }
$firebase_config = json_decode(file_get_contents($firebase_config_path), true);
$firebase = (new FirebaseFactory)->withServiceAccount($firebase_config);
$this->messaging = $firebase->createMessaging();
$this->isFirebaseInitialized = true;
}
/**
* Sends a notification to a user or all devices.
*
* @param int $userId The user ID. Set to 0 to send to all devices.
* @param string $title The notification title.
* @param string $body The notification body.
* @param array $data Optional data payload.
* @param bool $allDevices Send to all devices (including inactive) if true, otherwise only active devices.
* @param string|null $deviceType Optional device type filter (ios, android, web).
* @param array $actions Array of actions for call-style notification (e.g., ['accept', 'reject']).
*
*
* @return array An array containing 'error' (boolean) and 'message' (string) indicating success or failure.
*/
public function sendNotification($userId, $title , $body , $data = [], $allDevices = false, $deviceType = null, $actions = [], $isSilent = false){
$response = [
'error' => false,
'message' => '',
'messages' => []
];
$errorOccured = false;
// Check if firebase is initiallized succesfully
if (!$this->isFirebaseInitialized) {
$response['message'] = $this->errorMessage;
error_log($response['message']);
return $response;
}
// Get the user registration token based on the user id
$db = Factory::getContainer()->get('DatabaseDriver');;
$query = $db->getQuery(true);
$query->select('fcm_token');
$query->from('#__firebase_notifications');
if ($userId>0) $query->where('user_id = ' . (int) $userId);
if (!$allDevices) $query->where('is_active = 1'); // Send to all active devices
if ($deviceType) $query->where('device_type = ' . $db->quote($deviceType));
$db->setQuery($query);
$registrationTokens = $db->loadColumn();
if (empty($registrationTokens)) {
$response['message'] = 'No registration tokens found for user ID: ' . $userId;
error_log($response['message']);
return $response;
}
// Continue to send the notification
if (!$isSilent) {
$notification = [
'title' => $title,
'body' => $body,
];
};
foreach ($registrationTokens as $registrationToken) {
try {
// Create the message
$message = FirebaseCloudMessage::withTarget('token', $registrationToken)
->withData($data);
if (!$isSilent) {
$message= $message->withNotification($notification);
}
// Add actions if provided
if (!empty($actions)) {
// $message = $message->withData(['actions' => $actions]);
$message = $message->withData(array_merge($data, ['actions' => json_encode($actions)]));
// Android-specific configuration
$message = $message->withAndroidConfig([
'priority' => 'high',
// 'click_action' => 'CALL_CATEGORY',
]);
// iOS-specific configuration
$message = $message->withApnsConfig([
'mutable_content' => 1,
'content_available' => 1,
'alert' => '',
'sound' => 'default',
'priority' => 'high',
]);
}
$firebase_response = $this->messaging->send($message); // Send the message
if (isset($firebase_response['failure'])) {
$errorOccured = true;
$response['messages'][] ='Error sending notification to token ' . $registrationToken . ': ' . $firebase_response['failure'];
}else{
$response['messages'][] = 'Notification to token ' . $registrationToken . ' sended successfully';
}
} catch (FirebaseMessagingException $e) {
$errorOccured = true;
if (strpos($e->getMessage(), 'Requested entity was not found') !== false) {
$response['messages'][] = 'Error sending notification to token ' . $registrationToken . '(invalid token) : ' . $e->getMessage() . " deleting token...";
// Remove invalid token from database
$this->removeInvalidToken($registrationToken);
} else {
// Handle other FirebaseMessagingExceptions differently
$response['messages'][] = 'Temporary error sending notification to token ' . $registrationToken . ': ' . $e->getMessage();
// You might log the error or retry later
}
}
}
if (!$errorOccured) {// All messages sent successfully
$response['message'] = 'Notification sent successfully to '.(!$allDevices?'the active devices':'all devices').'!';
} else {
$response['error'] = true;
$response['message'] = 'Some notifications failed to send';
}
if($response['error']){
error_log($response['message']);
}
return $response;
}
} |
I'm pretty sure that the correct keys are I'd also suggest to try to remove |
You re right. i followed also this https://firebase-php.readthedocs.io/en/7.15.0/cloud-messaging.html because i saw i was passing the config parameters the wrong way. |
@niosme setting the |
Could someone provide a complete json of what you send? Maybe I can catch my mistake |
it works fine. But the background message listener is not triggering. Only the frontend listener works as expected. |
Yes, in fact, as you suggest, that background doesn't work for me either :S |
Maybe we can find a workaround here. |
Made it work like this AppDelegate.swift ( just copy paste this code and keep the previous if the bug is fixed in a future version )
and also at ios directory info.plist
in main.dart inside initState put those ( Just realized that tha main.dart code is not needed )
|
@justChris - I have a fix/workaround on this branch if you want to test it out: #13572 Would be helpful if anyone else can confirm as well, please 🙏 |
Note - I tested on iOS 18.1 and it seems it was fixed without any intervention on FlutterFire. |
oh yeah you're right, I totally forgot about that To fix, replace # https://github.com/firebase/flutterfire/pull/13525
# TODO: Switch to upstream when it's released to pub.dev
firebase_messaging:
git:
url: https://github.com/firebase/flutterfire.git
path: packages/firebase_messaging/firebase_messaging
ref: 8ff0f88 I do not suggest editing |
Is there an existing issue for this?
Which plugins are affected?
Messaging
Which platforms are affected?
iOS
Description
Since I upgraded to xcode16.0 and iOS18 the onMessage listener fires twice every time a message is received. This only happens with the onMessage listener, means when the app is in foreground. When the app is in background or terminated, this does NOT happen. And also this only happens on physical devices with iOS18. On devices with iOS17, the listener fires once per message, as expected.
I ensured that the listener is not subscribed multiple times, but still it fires twice.
Reproducing the issue
Firebase Core version
3.5.0
Flutter Version
3.24.3
Relevant Log Output
Flutter dependencies
Expand
Flutter dependencies
snippetAdditional context and comments
No response
The text was updated successfully, but these errors were encountered: