FirebaseMessagingService子类未调用onMessageReceived的FCM通知处理问题
先来说说你最困惑的核心问题:自定义的FirebaseMessagingService子类看似完全不起作用——能正常收通知但改不了内容,删掉代码功能不受影响,断点调试和Log输出也没反应。这大概率是消息类型不匹配或者服务配置有疏漏导致的,咱们一步步排查:
一、自定义MessagingService无效的原因及解决
区分FCM的两种消息类型
FCM推送分两种核心类型:- 通知消息(Notification Message):带
notification字段的推送,FCM SDK会直接在系统托盘显示通知,不会触发onMessageReceived方法。这就解释了为什么你删代码还能收通知——因为根本没走你的自定义逻辑! - 数据消息(Data Message):只有
data字段的推送,或者App处于前台状态时的通知消息,才会进入onMessageReceived,这时候你的自定义代码才会生效。
你可以检查下推送的payload,如果是从Firebase控制台发送的,默认是通知消息,要切换到「自定义数据」模式发数据消息,或者同时包含
notification和data字段。- 通知消息(Notification Message):带
验证Manifest中的服务配置
确保你的自定义服务在Manifest里声明正确,没有拼写错误,也没有重复声明默认服务:<service android:name=".YourCustomMessagingService" <!-- 替换成你的子类全路径 --> android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>另外要确认包名
com.e...和推送目标包名完全一致,控制台填错包名也会导致服务无法触发。检查Gradle依赖版本
确保firebase-messaging的依赖版本和其他Firebase组件版本匹配,避免版本冲突导致服务无法注册:implementation 'com.google.firebase:firebase-messaging:23.4.0' <!-- 建议使用最新稳定版 -->
二、提取推送内容中的数字作为Intent Extra失败的解决
搞清楚上面的问题后,提取数字的逻辑才能正常执行。这里给你一套可行的方案:
确保能拿到推送数据
如果是数据消息,在onMessageReceived里通过remoteMessage.getData()获取所有字段:@Override public void onMessageReceived(RemoteMessage remoteMessage) { // 获取推送的产品名称,比如"Nike45" String productName = remoteMessage.getData().get("product_name"); if (productName == null) return; // 提取数字部分 String productId = extractNumbers(productName); if (productId == null) return; // 构建Intent并传入Extra参数 Intent intent = new Intent(this, TargetActivity.class); intent.putExtra("PRODUCT_ID", productId); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 创建PendingIntent,用于点击通知跳转 PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE); // 自定义通知并显示 NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "CHANNEL_ID") .setContentTitle("自定义通知标题") .setContentText(productName) .setSmallIcon(R.drawable.ic_notification) .setContentIntent(pendingIntent) .setAutoCancel(true); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.notify(1, builder.build()); } // 提取字符串中的数字 private String extractNumbers(String input) { // 用正则匹配所有连续数字 Pattern pattern = Pattern.compile("\\d+"); Matcher matcher = pattern.matcher(input); if (matcher.find()) { return matcher.group(); } return null; }后台点击通知获取Extra的注意事项
如果推送同时包含notification和data字段,App后台时系统会自动显示通知,点击通知跳转后,data字段会附加到启动的Activity的Intent中。你需要在目标Activity的onCreate或onNewIntent中获取:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_target); // 获取Extra参数 String productId = getIntent().getStringExtra("PRODUCT_ID"); if (productId != null) { // 执行你的业务逻辑 } }注意:如果Activity的启动模式是
standard,每次点击通知都会创建新实例,建议设置为singleTop或singleTask,避免重复创建,同时在onNewIntent中更新Intent数据。
最后总结几个关键检查点
- 先确认推送的消息类型,只有数据消息或前台状态下的通知消息才会触发自定义服务
- 核对Manifest中的服务声明和包名是否完全匹配
- 用正则表达式确保能准确提取字符串中的数字
- 测试时优先用数据消息,这样能直接验证
onMessageReceived中的逻辑
内容的提问来源于stack exchange,提问作者user8755268

