FCM通知被归类为杂项且自定义通知通道不生效求助
核心问题1:后台时FCM通知消息绕过自定义通道
当应用处于后台时,FCM发送的**通知消息(包含notification字段的payload)**会由Android系统直接展示,不会触发onMessageReceived方法,也就不会执行自定义通道的创建代码,系统会使用默认通道将通知归为"杂项"。
核心问题2:通道属性设置顺序错误
你在调用notificationManager.createNotificationChannel(channel)之后才设置通道的灯光、振动等属性,这些修改不会生效——通道创建后需重新调用createNotificationChannel才能更新属性,正确流程是先配置所有属性再创建通道。
核心问题3:PendingIntent Flags适配问题
Android 12(API 31)及以上版本要求创建PendingIntent必须指定FLAG_IMMUTABLE或FLAG_MUTABLE,否则会抛出异常,可能导致通知无法正常展示。
具体修复步骤
1. 调整通道创建的代码顺序
先配置通道所有属性,再执行创建操作,同时将通道ID改为无空格的规范命名:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "重要通知通道"; String description = "用于展示FCM推送的重要通知"; int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel channel = new NotificationChannel("fcm_notification_channel", name, importance); channel.setDescription(description); channel.enableLights(true); channel.setLightColor(Color.RED); channel.enableVibration(true); channel.setVibrationPattern(new long[]{0, 600, 600}); // 先设置所有属性,再创建通道 notificationManager.createNotificationChannel(channel); }
2. 适配Android 12+的PendingIntent Flags
更新PendingIntent创建代码,添加版本适配的Flags:
int pendingFlags; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { pendingFlags = PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE; } else { pendingFlags = PendingIntent.FLAG_ONE_SHOT; } PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, pendingFlags);
3. 提前创建通知通道
避免后台接收通知时通道未初始化,建议在Application类或主Activity的onCreate中提前创建通道:
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); createNotificationChannel(); } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "重要通知通道"; String description = "用于展示FCM推送的重要通知"; int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel channel = new NotificationChannel("fcm_notification_channel", name, importance); channel.setDescription(description); channel.enableLights(true); channel.setLightColor(Color.RED); channel.enableVibration(true); channel.setVibrationPattern(new long[]{0, 600, 600}); NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } } }
记得在AndroidManifest.xml中注册该Application类:
<application android:name=".MyApp" ...> ... </application>
4. 确保FCM通知使用自定义通道(二选一)
方式一:使用数据消息(推荐)
修改服务器端FCM payload,仅发送数据消息(仅含data字段),这样无论应用前后台,都会触发onMessageReceived,由自定义代码展示通知:
{ "to": "用户设备token", "data": { "title": "通知标题", "body": "通知内容", "imageUrl": "图片链接(可选)" } }
同时更新onMessageReceived的处理逻辑:
@Override public void onMessageReceived(RemoteMessage remoteMessage) { String title = remoteMessage.getData().get("title"); String body = remoteMessage.getData().get("body"); String imageUrl = remoteMessage.getData().get("imageUrl"); if (title != null && body != null) { sendNotification(title, body, imageUrl); } }
方式二:在通知消息中指定通道ID
若必须使用通知消息(含notification字段),需在服务器payload中添加android.channel_id字段指定自定义通道ID:
{ "to": "用户设备token", "notification": { "title": "通知标题", "body": "通知内容", "image": "图片链接(可选)" }, "android": { "notification": { "channel_id": "fcm_notification_channel" } } }
额外注意事项
- 测试前请卸载旧版本应用,清除旧通道缓存后重新安装。
- Android O及以上版本,通知优先级由通道的
importance决定,NotificationCompat.PRIORITY_HIGH仅对Android N及以下生效,确保通道importance设为IMPORTANCE_HIGH以获得高优先级展示。
内容的提问来源于stack exchange,提问作者knight Fiury

