Flutter FCM Part 2: Subscribing to Topics, Broadcasting Notifications, and Navigating to Screens
In this part, we’ll expand our Firebase Cloud Messaging (FCM) setup to demonstrate the following functionalities:
1. Subscribing Devices to a Topic
2. Broadcasting Notifications to All Devices
3. Handling Navigation to a Screen on Notification Click
We’ll also include scripts for generating FCM tokens and sending notifications via Firebase Admin SDK to enable server-side integration.
1. Subscribing to a Topic
The updated NotificationService class already includes a method to subscribe to a topic:
Future<void> subscribeToTopic(String topic) async {
await FirebaseMessaging.instance.subscribeToTopic(topic);
print("Subscribed to $topic");
}
In the initialize method, devices are subscribed to the all_devices topic:
await subscribeToTopic('all_devices');
This ensures that all devices automatically subscribe to the `all_devices` topic upon initialization.
2. Broadcasting Notifications to All Devices
To broadcast notifications, you need to:
- Generate an OAuth2 token.
- Send the notification via the Firebase Admin SDK.
Generating OAuth2 Token
The following script uses google-auth-library to generate an OAuth2 token.
Save the following script in a file, e.g., generateToken.js:
const { GoogleAuth } = require('google-auth-library');
const auth = new GoogleAuth({
keyFile: './serviceaccount.json', // Path to your downloaded JSON key file
scopes: 'https://www.googleapis.com/auth/firebase.messaging'
});
async function getAccessToken() {
const client = await auth.getClient();
const accessToken = await client.getAccessToken();
return accessToken.token;
}
getAccessToken().then(token => {
console.log('Generated OAuth2 token:', token);
// Use this token for your Firebase request
}).catch(error => {
console.error('Error generating token:', error);
});
Dependencies:
Run the following command to install dependencies:
npm install google-auth-library
Sending Notifications to the Topic
Once you have the token, use the following script to send notifications to the all_devices topic. Save it in a file, e.g., sendNotification.js:
// npm install axios
const axios = require('axios');
const token = 'YOUR_GENERATED_TOKEN'; // Replace with your generated token
const url = 'https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send';
const messagePayload = {
message: {
topic: "all_devices",
notification: {
title: "Broadcast Notification",
body: "This message is sent to all devices!"
},
data: {
type: "chat" // Used for navigation
},
android: {
priority: "high",
notification: {
channel_id: "high_importance_channel"
}
}
}
};
const headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
axios.post(url, messagePayload, { headers })
.then(response => {
console.log('Message sent successfully:', response.data);
})
.catch(error => {
console.error('Error sending message:', error.response ? error.response.data : error.message);
});
Replace `YOUR_PROJECT_ID` with your Firebase project ID.
3. Handling Navigation on Notification Click
The NotificationService class handles navigation to a specific screen (`ChatScreen`) when a notification is clicked:
Notification Payload
In the messagePayload, include a data field to specify the type of notification:
"data": {
"type": "chat"
}
Handling the Data
The NotificationService processes the type field in the _handleBackgroundMessage method:
void _handleBackgroundMessage(String message) {
if (message == 'chat') {
navigatorKey.currentState?.push(MaterialPageRoute(
builder: (context) => ChatScreen(),
));
}
}
4. Testing the Implementation
Steps to Test:
1. Run the Flutter App: Ensure that NotificationService.initialize() is called in the main method.
2. Subscribe to the Topic: All devices will automatically subscribe to the all_devices topic.
3. Send Notifications: Use the sendNotification.js script to broadcast notifications.
4. Verify Navigation: On receiving the notification, tapping it should navigate to the ChatScreen.
5. Updated Code Highlights
Main Entry (`main.dart`)
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await NotificationService.instance.initialize();
runApp(MyApp());
}
Notification Service Updates
- Foreground Notification: Shows notifications immediately.
- Background Notification: Navigates to ChatScreen based on the type field.
Conclusion
This guide demonstrates how to:
1. Subscribe devices to an FCM topic.
2. Broadcast notifications to all devices.
3. Handle custom data for navigation in Flutter.
With the server-side scripts, you can seamlessly integrate backend services to manage notifications for your app.