From 3c299a09b499b2e45665a053f397a8a7e10b0e53 Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Sat, 11 Jul 2026 14:24:33 +0330 Subject: [PATCH] fcm implementations guide for flutter added --- fcm_registration_guide.md | 147 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 fcm_registration_guide.md diff --git a/fcm_registration_guide.md b/fcm_registration_guide.md new file mode 100644 index 0000000..c0fe6f3 --- /dev/null +++ b/fcm_registration_guide.md @@ -0,0 +1,147 @@ +# Guide: FCM Token Registration & Sync for Flutter + +This document details how the Flutter mobile app should manage, retrieve, and send the device's Firebase Cloud Messaging (FCM) token to the backend server. Syncing the FCM token is required to ensure users receive push notifications on their devices. + +--- + +## 1. API Endpoint Details + +The backend provides a dedicated endpoint to update the FCM token of the currently authenticated user. + +* **URL**: `/api/account/update-fcm/` +* **Method**: `POST` +* **Headers**: + * `Content-Type: application/json` + * `Authorization: Token ` (Token Authentication required) +* **Request Body**: + ```json + { + "fcm": "YOUR_FIREBASE_FCM_TOKEN" + } + ``` +* **Success Response (200 OK)**: + ```json + { + "detail": "FCM token updated successfully." + } + ``` +* **Error Response (401 Unauthorized)**: + * Returned if the authorization header is missing, incorrect, or expired. + +--- + +## 2. When to Send the FCM Token + +To prevent notification delivery failures, the Flutter application must send the FCM token to the backend in the following three scenarios: + +1. **On Successful Login / Account Verification**: + As soon as the user logs in (`/api/account/login/`) or verifies their verification code (`/api/account/verify/`) and obtains their authentication token, retrieve the FCM token and upload it. +2. **On App Start (If Logged In)**: + If the user has an active session saved locally, retrieve the current FCM token on app launch and sync it to the backend. This handles cases where the user's token might have refreshed while the app was closed. +3. **On Token Refresh Event**: + Firebase periodically refreshes device tokens. Listen to Firebase's token refresh stream and upload the new token immediately if the user is authenticated. + +--- + +## 3. Flutter (Dart) Implementation Example + +Here is a complete integration example using `firebase_messaging` and the `dio` (or `http`) package: + +```dart +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; + +class FcmTokenManager { + final Dio _dio = Dio(BaseOptions(baseUrl: 'https://api.yourdomain.com')); + + // Replace with your local storage lookup (e.g. FlutterSecureStorage or SharedPreferences) + Future getAuthToken() async { + return "SAVED_USER_AUTH_TOKEN"; + } + + /// Retrieves the current FCM token and sends it to the backend. + Future syncTokenToBackend() async { + try { + final String? authToken = await getAuthToken(); + if (authToken == null) { + debugPrint("User is not authenticated. Skipping FCM sync."); + return; + } + + // 1. Get token from Firebase + String? fcmToken = await FirebaseMessaging.instance.getToken(); + if (fcmToken == null) { + debugPrint("Failed to retrieve FCM token from Firebase."); + return; + } + + debugPrint("FCM Token retrieved: $fcmToken"); + + // 2. Send token to backend + final response = await _dio.post( + '/api/account/update-fcm/', + data: {'fcm': fcmToken}, + options: Options( + headers: { + 'Authorization': 'Token $authToken', + 'Content-Type': 'application/json', + }, + ), + ); + + if (response.statusCode == 200) { + debugPrint("FCM token synced successfully: ${response.data}"); + } + } catch (e) { + debugPrint("Error syncing FCM token: $e"); + } + } + + /// Setup listeners for token refreshes. + void setupTokenRefreshListener() { + FirebaseMessaging.instance.onTokenRefresh.listen((newFcmToken) async { + debugPrint("FCM Token refreshed: $newFcmToken"); + final String? authToken = await getAuthToken(); + if (authToken != null) { + // Sync token immediately since user is authenticated + await _dio.post( + '/api/account/update-fcm/', + data: {'fcm': newFcmToken}, + options: Options( + headers: { + 'Authorization': 'Token $authToken', + }, + ), + ); + } + }); + } +} +``` + +--- + +## 4. Best Practices for Mobile Developers + +1. **Clear Token on Logout**: + When the user logs out, it is critical to call `/api/account/update-fcm/` passing `null` or an empty string `""` before deleting the auth token locally. This prevents the device from continuing to receive push notifications destined for the logged-out user: + ```json + { + "fcm": "" + } + ``` +2. **Handle Token Request Permissions**: + On iOS, you must request permission before fetching the token: + ```dart + NotificationSettings settings = await FirebaseMessaging.instance.requestPermission( + alert: true, + badge: true, + sound: true, + ); + if (settings.authorizationStatus == AuthorizationStatus.authorized) { + syncTokenToBackend(); + } + ``` +3. **Avoid Redundant Calls**: + You can cache the last successfully synced FCM token in local storage (e.g. `SharedPreferences`). Compare the current token with the cached one on app start, and only perform the network request if they differ.