androidiosflutterfirebasefirebase-cloud-messaging

FCM data-message not received instantly on both iOS and Android in release mode


I am building a chat part in my flutter app. I was pushing my notifications as Notifications and not as only-data messages using FCM service. I faced a problem of firebase collapsing notifications if the user wasn't online, where it will only push the last notification, but I was relying on the notifications for payload to update the chats and chat messages. I had to change to only-data messages to avoid the collapsing issue. it was wroking in debug mode when the app was in foreground and background on both Android and iOS. I wanted to test if the app was terminated, and I found that the data messages will not be received until the user opens the app, whether the app was in background or terminated. While if I use normal notifications, it would always be received. Can someone help me understand and solve this issue ?

Laravel FCM function:

public function sendDataMessage($deviceTokens, $data = [], $priority = "high")
    {
        $messaging = app('firebase.messaging');
        $clean_data = $data;
        if (isset($data["type"]) && $data["type"] == "chat" && $data["action"] == "receiveMessage") {
            unset($clean_data["fcm_message"]);
        }
        $messages = [];
        foreach ($deviceTokens as $token) {
            try {
                if (isset($data["type"]) && $data["type"] == "chat" && $data["action"] == "receiveMessage") {
                    $chat_message = $data["fcm_message"];
                    $clean_data["title"] = Chats::select("name")->find($data["chat_id"])->name;
                    $clean_data["body"] = $chat_message["sender"]["name"] . ": " . ($chat_message["content"]["type"] == "Text" ? $chat_message["content"]["body"] : $chat_message["content"]["type"]);
                }
                $messages[] = CloudMessage::withTarget('token', $token)
                    ->withData($clean_data)
                    // ->withNotification(Notification::create("Asdasdoqoijwdioqs", "asdasd"))
                    ->withAndroidConfig(AndroidConfig::fromArray([
                        'priority' => 'high',  // Use high priority
                        'ttl' => 86400 * 28, // 4 weeks in seconds
                        // 'notification' => [
                        //     'tag' => isset($data["type"]) && $data["type"] == "chat" && $data["action"] == "receiveMessage" ? strval($chat_message["id"]) : "1",
                        //     'sound' => 'default',  // Ensure notification has sound
                        //     'channel_id' => 'high_importance',  // Use the notification channel defined in your Android app
                        // ],
                    ]))
                    ->withApnsConfig(ApnsConfig::fromArray([
                        'headers' => [
                            'apns-collapse-id' => isset($data["type"]) && $data["type"] == "chat" && $data["action"] == "receiveMessage" ? strval($chat_message["id"]) : "1",
                            'apns-expiration' => strval(time() + 86400 * 28), // Expiry timestamp
                            'apns-priority' => '10',
                        ],
                        'payload' => [
                            'aps' => [
                                // 'sound' => 'default',
                                "content-available" => 1,
                                "mutable-content" => 1
                            ],
                        ],
                    ]));
            } catch (Exception $e) {
                return $e;
            }
        }
        try {
            $report = $messaging->sendAll($messages);
        } catch (NotFound $e) {
            return $e;
        } catch (Exception $e) {
            return $e;
        }

        return $report->successes()->count();
    }

EDIT

I tried re-running the app in profile mode and it worked just fine. seems like it's a flutter release mode problem. I don't know if release mode behaviour is the one that will happen if uploaded to app store and play store. I'll try and update soon.


Solution

  • The problem specific to not receiving data messages was not because of Firebase but becauses of the background handler as it didn't have @pragma('vm:entry-point') so that Flutter doesn't remove the function when shaking down when trying to run in release as descibed in Firebase receive message documentation