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

Firebase Topic通知跳转逻辑失效及送达异常求助

问题描述

开发请假应用时,计划通过Firebase Topic实现跨Activity通知传递(MainActivity→DepartmentHead→Admin),遇到以下问题:

  • FirebaseMessagingService中的IF条件判断完全无效
  • 两个不同Topic的通知无法正确送达对应页面,点击通知无法跳转至目标Activity
  • 需要解决通知携带数据的问题

应用无崩溃,但通知功能无法正常工作。


关键代码

FirebaseMessagingService核心代码

public class FirebaseNoficationservices extends FirebaseMessagingService {
    private final String CHANNEL_ID="channel_id";
   Intent intent;

    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        Log.d("remote", remoteMessage.getData().toString());
        if((FirebaseMessaging.getInstance().subscribeToTopic("ahmedraza"))!=null){
            intent = new Intent(getApplicationContext(), DepartmentHead.class);
        }
        else if((FirebaseMessaging.getInstance().subscribeToTopic("ahmedraza"))!=null){
            intent = new Intent(getApplicationContext(), Admin.class);
        }

        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            int notificationId = new Random().nextInt();
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                createNotificationChannel(manager);
            }

            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.putExtra("key", remoteMessage.getData().get("name"));

            PendingIntent intent1 = PendingIntent.getActivities(this, 0, new Intent[]{intent}, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
            Notification notification;
            notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setContentTitle(remoteMessage.getData().get(getString(R.string.name)))
                    .setContentText(remoteMessage.getData().get(getString(R.string.department)))
                    .setSmallIcon(R.drawable.rx_notification)
                    .setAutoCancel(true)
                    .setContentIntent(intent1)
                    .build();
            manager.notify(notificationId, notification);
        }
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void createNotificationChannel(NotificationManager manager) {
        NotificationChannel channel=new NotificationChannel(CHANNEL_ID,"channelName",NotificationManager.IMPORTANCE_HIGH);
        channel.setDescription("My description");
        channel.enableLights(true);
        channel.setLightColor(android.R.color.white);
        manager.createNotificationChannel(channel);
    }
}

MainActivity发送通知代码

if(sendtoDepthead.isChecked()) {
    PushNotification notification = new PushNotification(new notificationData(fulnamee.getText().toString(), spinner.getSelectedItem().toString()), TOPIC);
    sendNotification(notification);
    Toast.makeText(MainActivity.this, "notification sent to manager", Toast.LENGTH_SHORT).show();
}
if(sendtoGeneralmanager.isChecked()){
    PushNotification notification = new PushNotification(new notificationData(fulnamee.getText().toString(), spinner.getSelectedItem().toString()), TOPICS);
    sendNotification(notification);
    Toast.makeText(MainActivity.this, "notification sent to manager", Toast.LENGTH_SHORT).show();
}

DepartmentHead订阅及转发代码

FirebaseMessaging.getInstance().subscribeToTopic(TOPIC);

FirebaseMessaging.getInstance().subscribeToTopic(TOPIC)
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                String msg = "Subscribed";
                if (!task.isSuccessful()) {
                    msg = "Subscribe failed";
                }
                Log.d(TAG, msg);
                Toast.makeText(DepartmentHead.this, msg, Toast.LENGTH_SHORT).show();
            }
        });
// 转发到Admin
PushNotification notification=new PushNotification(new notificationData(nam.getText().toString(),dept.getText().toString()),TOPICS);
sendNotification(notification);
Toast.makeText(DepartmentHead.this,"notification sent to manager",Toast.LENGTH_SHORT).show();

Admin订阅代码

FirebaseMessaging.getInstance().subscribeToTopic(TOPICS)
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                String msg = "Subscribed";
                if (!task.isSuccessful()) {
                    msg = "Subscribe failed";
                }
                Log.d(TAG, msg);
                Toast.makeText(Admin.this, msg, Toast.LENGTH_SHORT).show();
            }
        });

解决方案

1. 修复条件判断逻辑

原代码中用FirebaseMessaging.getInstance().subscribeToTopic()判断订阅状态完全错误,这个方法是执行订阅操作,返回的Task对象永远不为null,导致条件失效。

正确做法:通过RemoteMessage的from字段判断消息来源Topic(格式为/topics/xxx),以此区分目标页面。

2. 修正通知跳转逻辑

原代码误用PendingIntent.getActivities(),应改为PendingIntent.getActivity();同时设置正确的Intent Flag,避免页面栈混乱。

3. 确保通知数据正确携带

发送端要保证数据字段与接收端key一致,接收端提取数据后通过Intent传递到目标Activity。


修正后的关键代码

FirebaseMessagingService代码

public class FirebaseNoficationservices extends FirebaseMessagingService {
    private final String CHANNEL_ID = "channel_id";
    // 与发送端的Topic常量保持一致
    private static final String TOPIC_DEPT_HEAD = "ahmedraza";
    private static final String TOPIC_ADMIN = "admin_topic";

    @Override
    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        Log.d("remote", remoteMessage.getData().toString());

        Intent intent = null;
        // 通过消息来源Topic判断目标页面
        String fromTopic = remoteMessage.getFrom();
        if (fromTopic != null && fromTopic.equals("/topics/" + TOPIC_DEPT_HEAD)) {
            intent = new Intent(this, DepartmentHead.class);
        } else if (fromTopic != null && fromTopic.equals("/topics/" + TOPIC_ADMIN)) {
            intent = new Intent(this, Admin.class);
        }

        // 兜底处理,避免intent为null
        if (intent == null) {
            intent = new Intent(this, MainActivity.class);
        }

        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        int notificationId = new Random().nextInt();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createNotificationChannel(manager);
        }

        // 设置Intent Flag,确保跳转后页面栈正确
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        // 携带通知数据
        String userName = remoteMessage.getData().get("name");
        String department = remoteMessage.getData().get("department");
        intent.putExtra("key_name", userName);
        intent.putExtra("key_department", department);

        // 使用getActivity创建正确的PendingIntent,用notificationId作为requestCode避免重复
        PendingIntent pendingIntent = PendingIntent.getActivity(
                this,
                notificationId,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle(userName)
                .setContentText(department)
                .setSmallIcon(R.drawable.rx_notification)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent)
                .build();

        manager.notify(notificationId, notification);
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void createNotificationChannel(NotificationManager manager) {
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "请假通知", NotificationManager.IMPORTANCE_HIGH);
        channel.setDescription("处理请假申请的通知渠道");
        channel.enableLights(true);
        channel.setLightColor(Color.WHITE);
        manager.createNotificationChannel(channel);
    }
}

发送端数据类规范

确保notificationData的字段名与接收端一致,且包含getter方法(Firebase序列化需要):

public class notificationData {
    private String name;
    private String department;

    public notificationData(String name, String department) {
        this.name = name;
        this.department = department;
    }

    public String getName() { return name; }
    public String getDepartment() { return department; }
}

订阅逻辑优化

每个页面只订阅对应Topic,避免重复订阅:

  • DepartmentHead仅订阅TOPIC_DEPT_HEAD
  • Admin仅订阅TOPIC_ADMIN

内容的提问来源于stack exchange,提问作者Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 16:02:10