FCM接收数据正常但通知无法显示的问题排查与解决
Firebase通知无法显示的原因及修复方案
核心原因:Android 8.0+ 缺少强制要求的通知渠道
从Android 8.0(API Level 26)开始,系统强制要求所有通知必须关联通知渠道(Notification Channel),未配置渠道的通知会被系统拦截,无法显示。你的代码完全缺失通知渠道创建逻辑,这是通知不显示的首要原因。
修复步骤
1. 添加通知渠道创建逻辑
在sendLocalNotification方法开头加入渠道创建代码,适配高版本系统:
private void sendLocalNotification(String notificationTitle, String notificationBody, String url) { // Android 8.0+ 必须创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { String channelId = "app_notification_channel"; String channelName = "应用推送通知"; String channelDesc = "接收应用自定义推送通知"; int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel(channelId, channelName, importance); channel.setDescription(channelDesc); channel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), null); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel); } // 原有的notificationBuilder逻辑,注意添加channelId参数 NotificationCompat.Builder notificationBuilder; if(url == null || url.length() == 0) { Intent intent = new Intent(this, record_viewer.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 修复PendingIntent Flag(Android 12+ 必需) PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE); Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); // 这里必须指定channelId notificationBuilder = new NotificationCompat.Builder(this, "app_notification_channel") .setAutoCancel(true) .setSmallIcon(R.mipmap.ic_launcher) .setContentIntent(pendingIntent) .setContentTitle(notificationTitle) .setContentText(notificationBody) .setSound(defaultSoundUri); } else { Intent notificationIntent = new Intent(Intent.ACTION_VIEW); notificationIntent.setData(Uri.parse(url)); // 修复PendingIntent Flag(Android 12+ 必需) PendingIntent pending = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE); Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); // 这里必须指定channelId notificationBuilder = new NotificationCompat.Builder(this, "app_notification_channel") .setAutoCancel(true) .setSmallIcon(R.drawable.download_icon) .setContentIntent(pending) .setContentTitle(notificationTitle) .setContentText(notificationBody) .setSound(defaultSoundUri); } NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(1234, notificationBuilder.build()); }
2. 修复PendingIntent的Flag问题
Android 12(API Level 31)及以上版本要求创建PendingIntent时必须指定FLAG_IMMUTABLE或FLAG_MUTABLE,上述代码已将原有FLAG_ONE_SHOT与FLAG_IMMUTABLE结合使用,避免抛出异常导致通知创建失败。
3. 检查通知小图标有效性
Android系统要求通知小图标必须是透明背景的单色矢量图,如果你的R.mipmap.ic_launcher或R.drawable.download_icon是带背景的彩色图标,可能会导致通知显示空白方块。建议替换为符合规范的通知专用图标。
4. 确认Firebase服务注册正确
确保FirebaseMessagingService已在AndroidManifest.xml中正确注册:
<service android:name=".YourFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
同时确认google-services.json文件已正确放置在项目app目录下。
额外验证
- 测试时可先用Firebase控制台发送测试通知,确认基础推送功能正常后,再排查自定义payload的问题。
- 你的PHP payload仅包含
data字段,无论应用前台/后台都会触发onMessageReceived,修复上述问题后即可正常显示自定义通知。
内容的提问来源于stack exchange,提问作者user20355435
相关产品推荐
相关产品推荐

