Android Firebase新增数据时向所有用户推送通知实现问询
Hey Ahmad, great question! Since you’ve already got FCM configured, let’s walk through exactly how to set up that broadcast notification when a user posts an image. Here’s the step-by-step plan plus code snippets to make it work:
First, let’s outline the core steps you need to cover:
- Store every user’s FCM token in your database (so you can target all of them later)
- Trigger the notification logic right after a successful image upload to your database
- Fetch all valid FCM tokens from your database
- Build and send the broadcast notification via Firebase Admin SDK
1. Store User FCM Tokens in Your Database
Before you can send notifications, you need to collect and save each user’s FCM token when they log in. This token is unique per device/user combo.
Client-Side (Android Example)
When a user logs in, fetch their FCM token and save it to your database (I’ll use Firestore here since it’s common with Firebase):
// In your login success handler or MainActivity FirebaseMessaging.getInstance().token.addOnCompleteListener { task -> if (!task.isSuccessful) { Log.w("FCM_TOKEN", "Fetching token failed", task.exception) return@addOnCompleteListener } val token = task.result // Save token to Firestore, linked to the current user's UID FirebaseFirestore.getInstance() .collection("users") .document(FirebaseAuth.getInstance().currentUser!!.uid) .update("fcmToken", token, "isTokenInvalid", false) .addOnSuccessListener { Log.d("FCM_TOKEN", "Token saved successfully") } .addOnFailureListener { e -> Log.w("FCM_TOKEN", "Failed to save token", e) } }
2. Trigger Notification on Image Upload
Once your server confirms the image and its details are saved to the database, call the function that sends the broadcast.
Server-Side (Node.js with Firebase Admin SDK)
First, make sure you’ve initialized the Firebase Admin SDK (you should have this set up already):
const admin = require('firebase-admin'); const serviceAccount = require('./your-service-account-key.json'); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: 'https://your-project-id.firebaseio.com' });
Next, create a function to fetch all valid tokens from your database:
async function getAllValidTokens() { try { const usersSnapshot = await admin.firestore().collection('users').get(); const tokens = []; usersSnapshot.forEach(doc => { const userData = doc.data(); // Skip tokens that are missing or marked invalid if (userData.fcmToken && !userData.isTokenInvalid) { tokens.push(userData.fcmToken); } }); return tokens; } catch (error) { console.error('Error fetching tokens:', error); return []; } }
Then, build and send the broadcast notification:
async function sendPostNotification(postedByUsername) { const tokens = await getAllValidTokens(); if (tokens.length === 0) { console.log('No valid tokens to send notifications to'); return; } // Build the notification message const message = { notification: { title: 'New Post Alert!', body: `${postedByUsername} Post Something` }, tokens: tokens // Send to all fetched tokens }; try { const response = await admin.messaging().sendMulticast(message); console.log(`Sent ${response.successCount} notifications successfully`); console.log(`Failed to send ${response.failureCount} notifications`); // Optional: Mark failed tokens as invalid in the database const failedTokens = []; response.responses.forEach((resp, index) => { if (!resp.success) { failedTokens.push(tokens[index]); } }); if (failedTokens.length > 0) { const batch = admin.firestore().batch(); // Find each user with a failed token and mark it invalid for (const token of failedTokens) { const userQuery = await admin.firestore().collection('users') .where('fcmToken', '==', token).limit(1).get(); userQuery.forEach(doc => { batch.update(doc.ref, { isTokenInvalid: true }); }); } await batch.commit(); console.log('Marked invalid tokens in database'); } } catch (error) { console.error('Error sending notification:', error); } }
Finally, call this function right after your image upload logic completes:
// Example: After saving image and details to DB async function handleImageUpload(postedByUsername) { // ... your existing code to save image metadata to the database ... // Trigger the broadcast notification await sendPostNotification(postedByUsername); }
3. Client-Side Notification Handling
To display the notification on users’ devices, set up a Firebase Messaging Service:
Android Example
Create a service class to handle incoming notifications:
class MyMessagingService : FirebaseMessagingService() { override fun onMessageReceived(remoteMessage: RemoteMessage) { super.onMessageReceived(remoteMessage) remoteMessage.notification?.let { notification -> showSystemNotification(notification.title, notification.body) } } private fun showSystemNotification(title: String?, body: String?) { val intent = Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP } val pendingIntent = PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_IMMUTABLE ) val channelId = "NEW_POST_CHANNEL" val notificationBuilder = NotificationCompat.Builder(this, channelId) .setSmallIcon(R.drawable.ic_notification) .setContentTitle(title) .setContentText(body) .setAutoCancel(true) .setContentIntent(pendingIntent) .setPriority(NotificationCompat.PRIORITY_DEFAULT) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Create notification channel (required for Android 8.0+) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( channelId, "New Posts", NotificationManager.IMPORTANCE_DEFAULT ) notificationManager.createNotificationChannel(channel) } notificationManager.notify(0, notificationBuilder.build()) } }
Don’t forget to register this service in your AndroidManifest.xml:
<service android:name=".MyMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
Key Notes to Keep in Mind
- Token Cleanup: Always handle failed tokens by marking them invalid. This prevents unnecessary API calls and keeps your database clean.
- Batch Limits: The
sendMulticastmethod supports up to 500 tokens per request. If you have more than 500 users, split the tokens into chunks of 500 and send multiple requests. - Customization: You can add extra data to the notification (like the post ID) to let users tap directly to the new image instead of just the main activity.
内容的提问来源于stack exchange,提问作者Ahmad Abbas

