基于Firebase通知(Swift)实现单设备消息推送
Got it, let's walk through both how to send a push notification to a single iOS device via Firebase, and how to tie this to user-specific identifiers like phone numbers or usernames—this is totally doable, you just need to link those identifiers to the device's FCM token.
Firebase Cloud Messaging (FCM) identifies individual devices via a FCM Registration Token—this is the core of single-device pushes. Here's how to set it up:
Step 1: Get the FCM Token on iOS
First, you need to fetch the device's FCM token in your iOS app (Swift example):
import FirebaseMessaging import UserNotifications class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() Messaging.messaging().delegate = self // Request notification permissions UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in guard granted else { return } DispatchQueue.main.async { application.registerForRemoteNotifications() } } // Fetch initial token Messaging.messaging().token { token, error in if let error = error { print("Error fetching FCM token: \(error)") } else if let token = token { print("FCM Token: \(token)") // Save this token to your Firebase database (Firestore/Realtime DB) self.saveFCMTokenToDatabase(token: token) } } return true } // Listen for token updates (tokens can change when app is reinstalled, device is restored, etc.) func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { guard let token = fcmToken else { return } print("FCM Token updated: \(token)") saveFCMTokenToDatabase(token: token) } // Helper to save token to Firestore private func saveFCMTokenToDatabase(token: String) { // Assuming you have a current user authenticated via Firebase Auth guard let userId = Auth.auth().currentUser?.uid else { return } let db = Firestore.firestore() db.collection("users").document(userId).updateData([ "fcmToken": token ]) { error in if let error = error { print("Error saving token: \(error)") } } } }
Step 2: Send a Push to the Token
Once the token is stored, you have two reliable ways to send a push:
- Firebase Console: Head to Firebase Console > Cloud Messaging > New Notification. Under "Target", select "Single device" and paste the FCM token you saved.
- Firebase Admin SDK (ideal for server-side/automated pushes):
Here's a Node.js example:const admin = require('firebase-admin'); admin.initializeApp(); const sendSingleDevicePush = async (token) => { const message = { notification: { title: "Hey there!", body: "This is a test push to your specific device" }, token: token }; try { const response = await admin.messaging().send(message); console.log("Successfully sent message:", response); } catch (error) { console.log("Error sending message:", error); } }; // Call with the stored token from your database sendSingleDevicePush("YOUR_DEVICE_FCM_TOKEN");
To push via phone number, username, or other custom identifiers, you just need to create a mapping between that identifier and the user's FCM token in your database. Here's the step-by-step:
Step 1: Link User Identifiers to FCM Tokens
When a user signs up or logs in, store their phone number/username alongside their FCM token in your database. For example, in Firestore, your users collection documents might look like:
users/{userId} - phoneNumber: "+1234567890" - username: "matthewcho" - fcmToken: "DEVICE_FCM_TOKEN_HERE" - ... other user profile data
Update your iOS app's saveFCMTokenToDatabase function to include these identifiers when saving/updating the token.
Step 2: Fetch the Token by User Identifier (Server-Side)
Use the Firebase Admin SDK to query your database for the token associated with the user's phone number/username. Example in Node.js:
const getTokenByPhoneNumber = async (phoneNumber) => { const db = admin.firestore(); const snapshot = await db.collection("users").where("phoneNumber", "==", phoneNumber).get(); if (snapshot.empty) { console.log("No user found with that phone number"); return null; } // Assuming one user per phone number (adjust to an array if multiple devices are allowed) const userDoc = snapshot.docs[0]; return userDoc.data().fcmToken; };
Step 3: Send the Push to the Fetched Token
Combine the above with the send function we wrote earlier:
const sendPushByPhoneNumber = async (phoneNumber) => { const token = await getTokenByPhoneNumber(phoneNumber); if (token) { await sendSingleDevicePush(token); } }; // Call with the target user's phone number sendPushByPhoneNumber("+1234567890");
Key Notes to Avoid Headaches
- Handle multiple devices: If a user uses multiple devices, store an array of FCM tokens instead of a single string, then loop through them to send pushes to all their devices.
- Token freshness: Always listen for token updates (as shown in the iOS code) and update your database immediately—FCM tokens can expire or change when an app is reinstalled or a device is restored, so stale tokens will fail to deliver pushes.
- Security: Lock down your database rules to restrict access to user token data (e.g., only allow authenticated admins to query tokens by phone number/username).
内容的提问来源于stack exchange,提问作者Matthew Cho

