This guide shows how to integrate Firebase Cloud Messaging (FCM) with your React Native HRM app to receive push notifications when tasks are assigned.
npm install @react-native-firebase/app @react-native-firebase/messaging- Create project at https://console.firebase.google.com
- Add Android/iOS apps
- Download
google-services.json(Android) andGoogleService-Info.plist(iOS) - Follow platform-specific setup in Firebase docs
Create src/services/notificationService.ts:
import messaging from '@react-native-firebase/messaging';
import { Platform, PermissionsAndroid, Alert } from 'react-native';
// Request notification permissions
export const requestNotificationPermission = async (): Promise<boolean> => {
if (Platform.OS === 'android') {
if (Platform.Version >= 33) {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
);
return granted === PermissionsAndroid.RESULTS.GRANTED;
}
return true; // Auto-granted on Android < 13
}
// iOS
const authStatus = await messaging().requestPermission();
return (
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL
);
};
// Get FCM token
export const getFCMToken = async (): Promise<string | null> => {
try {
const token = await messaging().getToken();
console.log('FCM Token:', token);
return token;
} catch (error) {
console.error('Error getting FCM token:', error);
return null;
}
};
// Setup notification handlers
export const setupNotificationHandlers = (
onForegroundNotification: (message: any) => void,
onBackgroundNotification: (message: any) => void,
onNotificationOpenedApp: (message: any) => void
) => {
// Foreground notification handler
const unsubscribeForeground = messaging().onMessage(async (remoteMessage) => {
console.log('Foreground notification:', remoteMessage);
// Show in-app alert
Alert.alert(
remoteMessage.notification?.title || 'New Notification',
remoteMessage.notification?.body || '',
[
{
text: 'View',
onPress: () => onForegroundNotification(remoteMessage.data),
},
{ text: 'Dismiss', style: 'cancel' },
]
);
});
// Background notification opened handler
messaging().onNotificationOpenedApp((remoteMessage) => {
console.log('Notification opened app from background:', remoteMessage);
onBackgroundNotification(remoteMessage.data);
});
// Quit state notification opened handler
messaging()
.getInitialNotification()
.then((remoteMessage) => {
if (remoteMessage) {
console.log('Notification opened app from quit state:', remoteMessage);
onNotificationOpenedApp(remoteMessage.data);
}
});
return unsubscribeForeground;
};Create src/services/api.ts:
import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';
const api = axios.create({
baseURL: 'https://your-api-url.com/api/v1',
timeout: 10000,
});
// Add auth token interceptor
api.interceptors.request.use(async (config) => {
const token = await AsyncStorage.getItem('authToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Update FCM token function
export const updateFcmToken = async (userId: string, fcmToken: string) => {
try {
const response = await api.patch(`/users/fcm-token/${userId}`, {
fcmToken,
});
console.log('FCM token updated successfully');
return response.data;
} catch (error) {
console.error('Failed to update FCM token:', error);
throw error;
}
};
export default api;Update App.tsx:
import React, { useEffect } from 'react';
import { useNavigation } from '@react-navigation/native';
import messaging from '@react-native-firebase/messaging';
import {
requestNotificationPermission,
getFCMToken,
setupNotificationHandlers,
} from './services/notificationService';
import { updateFcmToken } from './services/api';
function App() {
const navigation = useNavigation();
useEffect(() => {
// Request permission and setup FCM
const initializeNotifications = async () => {
const hasPermission = await requestNotificationPermission();
if (hasPermission) {
const fcmToken = await getFCMToken();
if (fcmToken && user?.id) {
// Update FCM token on backend
await updateFcmToken(user.id, fcmToken);
}
}
// Setup notification handlers
const unsubscribe = setupNotificationHandlers(
// Foreground notification
(data) => {
if (data?.taskId) {
navigation.navigate('TaskDetail', { taskId: data.taskId });
}
},
// Background notification opened
(data) => {
if (data?.taskId) {
navigation.navigate('TaskDetail', { taskId: data.taskId });
}
},
// Quit state notification opened
(data) => {
if (data?.taskId) {
navigation.navigate('TaskDetail', { taskId: data.taskId });
}
}
);
return unsubscribe;
};
const unsubscribe = initializeNotifications();
// Listen for token refresh
const unsubscribeTokenRefresh = messaging().onTokenRefresh(async (token) => {
console.log('FCM Token refreshed:', token);
if (user?.id) {
await updateFcmToken(user.id, token);
}
});
return () => {
unsubscribe?.then((unsub) => unsub());
unsubscribeTokenRefresh();
};
}, [user]);
return (
// Your app components
);
}Update your login flow to register the FCM token:
// In your login function
const handleLogin = async (email: string, password: string) => {
try {
// Login API call
const response = await api.post('/auth/login', { email, password });
const { user, token } = response.data;
// Save auth token
await AsyncStorage.setItem('authToken', token);
await AsyncStorage.setItem('user', JSON.stringify(user));
// Get and register FCM token
const fcmToken = await getFCMToken();
if (fcmToken) {
await updateFcmToken(user.id, fcmToken);
}
// Navigate to home
navigation.navigate('Home');
} catch (error) {
console.error('Login failed:', error);
}
};Add to index.js:
import messaging from '@react-native-firebase/messaging';
// Register background handler
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
console.log('Message handled in the background!', remoteMessage);
});Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.INTERNET" />In Xcode:
- Open
ios/YourApp.xcworkspace - Select target → Signing & Capabilities
- Add "Push Notifications" capability
- Add "Background Modes" → Enable "Remote notifications"
1. User opens app
↓
2. Request notification permission
↓
3. Get FCM token from Firebase
↓
4. User logs in
↓
5. Send FCM token to backend (PATCH /users/fcm-token/:id)
↓
6. Token stored in MongoDB user document
↓
7. Manager creates task assigned to user
↓
8. NestJS publishes task.created event to Kafka (includes FCM token)
↓
9. Golang service consumes event
↓
10. Golang sends FCM push notification
↓
11. User receives notification on device
↓
12. User taps notification → Navigate to task details
- Login to the app
- Check console for FCM token
- Create a task assigned to this user via backend
- Verify push notification is received
- Tap notification and verify navigation to task details
- No token received: Check Firebase project setup and google-services.json/GoogleService-Info.plist
- Permission denied: Ensure permissions are requested before getting token
- Notifications not showing: Check app is properly configured in Firebase Console
- iOS notifications not working: Verify APNs certificates are uploaded to Firebase