You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android跨应用通知推送:基于Firebase向指定员工推送方案咨询

Hey there! Let's break down how to implement this targeted push notification feature step by step—since you already have the core setup (two apps connected to Firebase, report submission, and a way to match on-duty employees), this should fit right in.

Targeted Push Notifications for On-Duty Employees When a Report is Submitted

Core Tech Stack to Use

  • Firebase Cloud Messaging (FCM): Handles sending and receiving push notifications between your apps.
  • Firebase Cloud Functions: Triggers automatically when a new report is added to Realtime Database, fetches the right employee's FCM token, and sends the notification.
  • Firebase Realtime Database: Stores report data, employee schedules, and FCM tokens mapped to employee IDs.

Step 1: Store FCM Tokens for Employees

First, your employee app needs to save each employee's FCM token to the Realtime Database, linked to their unique employee ID. This lets your Cloud Function know exactly which device to send the notification to.

Android Code (Employee App)

Add this code to your employee app's main activity or a dedicated service to retrieve and save the FCM token:

import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.database.FirebaseDatabase

// Call this when the employee logs in or when the FCM token updates
fun saveFcmToken(employeeId: String) {
    FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
        if (!task.isSuccessful) {
            return@addOnCompleteListener
        }
        // Get new FCM registration token
        val token = task.result
        // Save token to Realtime Database at /fcmTokens/{employeeId}
        FirebaseDatabase.getInstance().getReference("fcmTokens/$employeeId")
            .setValue(token)
            .addOnSuccessListener {
                // Token saved successfully
            }
            .addOnFailureListener {
                // Handle error
            }
    }
}

// Also listen for token updates (FCM tokens can change over time)
class MyFirebaseMessagingService : FirebaseMessagingService() {
    override fun onNewToken(token: String) {
        super.onNewToken(token)
        // Get the currently logged-in employee's ID (you should have this stored locally)
        val currentEmployeeId = "EMP123" // Replace with actual employee ID retrieval logic
        saveFcmToken(currentEmployeeId)
    }
}

Don't forget to declare the service in your AndroidManifest.xml:

<service
    android:name=".MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

Step 2: Write a Cloud Function to Trigger Notifications

Next, create a Cloud Function that listens for new reports added to /reports in Realtime Database. When a new report is added, it will:

  1. Fetch the report details.
  2. Use your existing method to get the on-duty employee's ID.
  3. Retrieve that employee's FCM token from /fcmTokens.
  4. Send a push notification via FCM.

Cloud Function Code (Node.js)

First, make sure you have the Firebase CLI set up, then create a new function:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

exports.sendReportNotification = functions.database.ref("/reports/{reportId}")
    .onCreate(async (snapshot, context) => {
        // 1. Get the new report data
        const reportData = snapshot.val();
        const reportTitle = reportData.title;
        const reportDescription = reportData.description;
        const timestamp = reportData.timestamp;

        // 2. Get the on-duty employee ID using your existing method
        // Replace this with your actual logic to match the on-duty employee
        const onDutyEmployeeId = await getOnDutyEmployeeId(timestamp);

        if (!onDutyEmployeeId) {
            functions.logger.log("No on-duty employee found for this report");
            return null;
        }

        // 3. Fetch the employee's FCM token from the database
        const fcmTokenSnapshot = await admin.database()
            .ref(`/fcmTokens/${onDutyEmployeeId}`)
            .once("value");
        const fcmToken = fcmTokenSnapshot.val();

        if (!fcmToken) {
            functions.logger.log(`No FCM token found for employee ${onDutyEmployeeId}`);
            return null;
        }

        // 4. Build and send the notification
        const payload = {
            notification: {
                title: "New Report Submitted",
                body: `Title: ${reportTitle}\nDescription: ${reportDescription}`,
                clickAction: "OPEN_REPORT_DETAILS" // Optional: For deep linking
            },
            data: {
                reportId: context.params.reportId,
                reportTitle: reportTitle
                // Add any other data you need for the employee app
            },
            token: fcmToken
        };

        return admin.messaging().send(payload)
            .then((response) => {
                functions.logger.log("Notification sent successfully:", response);
                return response;
            })
            .catch((error) => {
                functions.logger.log("Error sending notification:", error);
                return error;
            });
    });

// Replace this with your existing method to get the on-duty employee ID
async function getOnDutyEmployeeId(timestamp) {
    // Example logic: Query your /schedules node to find the employee on duty at the timestamp
    const schedulesSnapshot = await admin.database()
        .ref("/schedules")
        .orderByChild("startTime")
        .endAt(timestamp)
        .orderByChild("endTime")
        .startAt(timestamp)
        .limitToFirst(1)
        .once("value");
    
    if (schedulesSnapshot.exists()) {
        const schedule = schedulesSnapshot.val();
        // Assuming schedules are stored as { employeeId: { startTime: ..., endTime: ... } }
        return Object.keys(schedule)[0];
    }
    return null;
}

Deploy this function using the Firebase CLI:

firebase deploy --only functions

Step 3: Handle Notifications in the Employee App

Finally, update your MyFirebaseMessagingService to handle incoming notifications and display them, plus handle deep linking if needed:

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat

class MyFirebaseMessagingService : FirebaseMessagingService() {
    private val CHANNEL_ID = "REPORT_NOTIFICATIONS"

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        
        // Create notification channel (required for Android O and above)
        createNotificationChannel()

        // Get notification data
        val title = remoteMessage.notification?.title ?: "New Report"
        val body = remoteMessage.notification?.body ?: "A new report has been submitted"
        val reportId = remoteMessage.data["reportId"]

        // Create intent to open report details activity
        val intent = Intent(this, ReportDetailsActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            putExtra("REPORT_ID", reportId)
        }
        val pendingIntent: PendingIntent = PendingIntent.getActivity(
            this, 0, intent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )

        // Build the notification
        val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_notification) // Replace with your app's icon
            .setContentTitle(title)
            .setContentText(body)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)

        // Show the notification
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.notify(0, notificationBuilder.build())
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = "Report Notifications"
            val descriptionText = "Alerts for new submitted reports"
            val importance = NotificationManager.IMPORTANCE_HIGH
            val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
                description = descriptionText
            }
            val notificationManager: NotificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }
}

Key Notes to Remember

  • Token Freshness: FCM tokens can expire or change, so always update the database when onNewToken is called in the employee app.
  • Security: Make sure your Realtime Database rules restrict access to /fcmTokens so only authenticated employees can write their own tokens. Example rule:
    {
      "rules": {
        "fcmTokens": {
          "$employeeId": {
            ".write": "$employeeId === auth.uid",
            ".read": "auth != null && auth.token.admin === true" // Allow Cloud Functions (admin) to read
          }
        }
      }
    }
    
  • Error Handling: The Cloud Function includes basic error handling, but you can expand it to handle cases where no token exists or the employee is not found (e.g., log to Firebase Crashlytics or send a fallback notification to a supervisor).

内容的提问来源于stack exchange,提问作者J. Adam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:37:47