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

Cordova Android后台/关闭状态下FCM带交互按钮推送实现问询

实现Cordova Android后台/关闭状态下FCM带交互按钮的推送通知

可以实现这个需求,你遇到的核心问题是应用被完全杀死后JS环境终止,无法触发前端的消息回调,必须通过Android原生层处理FCM消息并生成带按钮的通知。以下是基于你当前使用的cordova-plugin-firebasex和cordova-plugin-local-notification的具体实现方案:

一、调整FCM推送负载

后端推送时只发送data字段,不要包含notification字段。这样FCM会把消息直接传递到原生的FirebaseMessagingService,而非系统通知栏,确保应用在任何状态下都能捕获到消息:

{
  "to": "DEVICE_TOKEN",
  "data": {
    "title": "测试通知",
    "body": "是否确认操作?",
    "customData": "你的自定义业务数据"
  }
}

二、扩展Android原生代码(关键步骤)

cordova-plugin-firebasex默认的后台消息处理不支持自定义通知按钮,需要自定义FirebaseMessagingService来生成带交互按钮的通知:

1. 创建自定义MessagingService类

在你的Cordova项目的platforms/android/app/src/main/java/[你的包名]/下新建CustomFirebaseMessagingService.java:

package com.your.package.name; // 替换成你的应用包名

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
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;

public class CustomFirebaseMessagingService extends FirebaseMessagingService {
    private static final String CHANNEL_ID = "interactive_notifications";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        
        // 从data字段获取推送内容
        String title = remoteMessage.getData().get("title");
        String body = remoteMessage.getData().get("body");
        String customData = remoteMessage.getData().get("customData");

        // 创建通知渠道(Android O及以上必需)
        createNotificationChannel();

        // 构建按钮点击的Intent
        Intent yesIntent = new Intent(this, NotificationActionReceiver.class);
        yesIntent.setAction("YES_ACTION");
        yesIntent.putExtra("customData", customData);
        PendingIntent yesPendingIntent = PendingIntent.getBroadcast(this, 0, yesIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

        Intent noIntent = new Intent(this, NotificationActionReceiver.class);
        noIntent.setAction("NO_ACTION");
        noIntent.putExtra("customData", customData);
        PendingIntent noPendingIntent = PendingIntent.getBroadcast(this, 1, noIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

        // 构建带按钮的通知
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.mipmap.ic_launcher) // 替换成你的通知图标
                .setContentTitle(title)
                .setContentText(body)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .addAction(R.drawable.ic_yes, "确认", yesPendingIntent) // 按钮图标、文字、Intent
                .addAction(R.drawable.ic_no, "取消", noPendingIntent);

        // 显示通知
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify((int) System.currentTimeMillis(), builder.build());
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "交互通知";
            String description = "带按钮的通知渠道";
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
            channel.setDescription(description);
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }
}

2. 创建通知按钮的广播接收器

同样在包名下新建NotificationActionReceiver.java,用于处理按钮点击事件并传递到JS层:

package com.your.package.name;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONObject;

public class NotificationActionReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        String customData = intent.getStringExtra("customData");

        try {
            JSONObject data = new JSONObject();
            data.put("action", action);
            data.put("customData", customData);

            // 发送消息到JS层
            if (CordovaWebView.getWebView() != null) {
                PluginResult result = new PluginResult(PluginResult.Status.OK, data);
                result.setKeepCallback(true);
                CordovaWebView.getWebView().sendPluginResult(result, "notificationAction");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. 修改AndroidManifest.xml

在platforms/android/app/src/main/AndroidManifest.xml中注册自定义服务和广播接收器,替换插件默认的FirebaseMessagingService:

<!-- 移除插件默认的MessagingService注册(如果存在) -->
<!-- <service android:name="com.google.firebase.messaging.FirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service> -->

<!-- 注册自定义MessagingService -->
<service
    android:name=".CustomFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

<!-- 注册广播接收器 -->
<receiver
    android:name=".NotificationActionReceiver"
    android:exported="false">
    <intent-filter>
        <action android:name="YES_ACTION" />
        <action android:name="NO_ACTION" />
    </intent-filter>
</receiver>

三、JS层接收按钮点击事件

在前端代码中添加监听原生传递的按钮点击事件,保留原有的token获取逻辑:

import { getDevice } from "framework7/lite-bundle";

function setupPushNotification(getTokenCallBack) {
  const device = getDevice();
  if (device.cordova) {
    FirebasePlugin.getToken((token) => getTokenCallBack(token));
    
    // 监听原生传递的通知按钮点击事件
    window.addEventListener('notificationAction', (event) => {
      const { action, customData } = event.detail;
      // 处理按钮点击后的业务逻辑,比如请求后端更新状态
      console.log(`用户点击了${action},自定义数据:${customData}`);
    });
  }
}

// 初始化推送
setupPushNotification((deviceToken) => {
  // 更新设备令牌到后端
});

四、注意事项

  • 后台权限:部分国产厂商(小米、华为、OPPO等)会限制应用后台服务,需要引导用户开启「自启动权限」和「后台弹出界面权限」,否则应用被杀死后可能无法接收FCM消息。
  • 通知图标:确保Android项目中存在通知图标资源(ic_yes、ic_no等),否则按钮会显示默认图标。
  • 插件版本兼容:当前使用的cordova-plugin-firebasex@14.2.1和cordova-plugin-local-notification@0.9.0-beta.2版本无需额外调整,但需确保原生代码与插件依赖不冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:55:28