initializeFcmToken method
Initializes FCM token management and syncs with server.
Call this after user is authenticated. The service will:
- Get the current FCM token
- Sync it to the server via
onTokenChanged - Listen for token refreshes and sync automatically
onTokenChanged is called when the token changes. Use this to sync
the token to your backend server. The callback receives:
newToken: The new FCM token (null if unregistering)oldToken: The previous FCM token (null if first registration)
Example:
await notificationService.initializeFcmToken(
onTokenChanged: (newToken, oldToken) async {
await myBackendService.updateFcmToken(newToken, oldToken);
},
);
Implementation
Future<void> initializeFcmToken({
required Future<void> Function(String? newToken, String? oldToken) onTokenChanged,
}) async {
if (_hasFcmTokenInitialized) {
logd('FCM token already initialized');
return;
}
_onTokenChanged = onTokenChanged;
// Handle APNS token for iOS/macOS
if (!kIsWeb && (Platform.isIOS || Platform.isMacOS)) {
await _waitForApnsToken();
}
// Get initial token
try {
final token = await FirebaseMessaging.instance.getToken();
if (token != null) {
final oldToken = await _getStoredToken();
// Prefer the persisted token as the source of truth for "old token"
// (cached in-memory values may be null on cold start).
if (token != oldToken) {
await _onTokenChanged!(token, oldToken);
await _storeToken(token);
}
_cachedFcmToken = token;
logd('FCM token initialized: ${token.substring(0, 20)}...');
}
} catch (e) {
loge(e, 'Failed to get FCM token');
return; // Non-critical, don't propagate
}
// Listen for token refreshes
_tokenRefreshSubscription = FirebaseMessaging.instance.onTokenRefresh.listen(
(newToken) async {
final oldToken = await _getStoredToken();
try {
await _onTokenChanged!(newToken, oldToken);
await _storeToken(newToken);
_cachedFcmToken = newToken;
logd('FCM token refreshed: ${newToken.substring(0, 20)}...');
} catch (e) {
loge(e, 'Error syncing refreshed token');
}
},
);
_hasFcmTokenInitialized = true;
logi('FCM token management initialized');
}