求助:Firebase推送通知点击后后台无法弹出AlertDialog问题
解决Firebase后台点击通知不弹出AlertDialog的问题
这个问题我之前也碰到过,核心原因是Firebase推送消息的类型差异导致后台和前台的处理逻辑不一样:
当App处于前台时,不管是通知消息还是数据消息,都会触发MyFirebaseMessagingService的onMessageReceived方法,所以你能直接在那里处理弹窗;但App在后台时,如果推送的是带notification字段的通知消息,系统会直接接管通知的显示,点击后默认打开你的启动Activity(也就是MainActivity),不会走onMessageReceived,所以你之前的弹窗逻辑根本没被触发。
下面给你两个可行的解决方案,根据你的推送需求选就行:
方案一:改用数据消息推送(推荐)
这种方式不管App在前台、后台还是被杀死,都会触发onMessageReceived,你可以完全自己控制通知的构建和点击逻辑:
1. 修改推送Payload
推送时只传data字段,不要包含notification字段,比如:
{ "data": { "title": "你的通知标题", "content": "你的通知内容" }, "to": "设备令牌" }
2. 在MyFirebaseMessagingService中构建通知并传递参数
在onMessageReceived里自己创建通知,同时把通知内容通过Intent传递给MainActivity:
@Override public void onMessageReceived(RemoteMessage remoteMessage) { // 提取数据消息里的内容 Map<String, String> data = remoteMessage.getData(); String notifyTitle = data.get("title"); String notifyContent = data.get("content"); // 构建点击通知后跳转的Intent,带上通知内容 Intent intent = new Intent(this, MainActivity.class); intent.putExtra("NOTIFY_TITLE", notifyTitle); intent.putExtra("NOTIFY_CONTENT", notifyContent); // 避免重复创建Activity,同时确保回到已存在的实例 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); // 创建PendingIntent(Android 12+必须加FLAG_IMMUTABLE) PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // 构建通知(记得先创建通知渠道,Android O及以上必需) NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "YOUR_CHANNEL_ID") .setSmallIcon(R.drawable.ic_notification) .setContentTitle(notifyTitle) .setContentText(notifyContent) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setContentIntent(pendingIntent) .setAutoCancel(true); // 发送通知 NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( "YOUR_CHANNEL_ID", "通知渠道名称", NotificationManager.IMPORTANCE_DEFAULT ); notificationManager.createNotificationChannel(channel); } notificationManager.notify(0, builder.build()); }
3. 在MainActivity中接收参数并弹出弹窗
不管是后台启动还是前台切换,都能拿到通知内容并弹窗:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 处理启动时的Intent handleNotification(getIntent()); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); // 处理后台切换回来的Intent handleNotification(intent); } private void handleNotification(Intent intent) { if (intent == null || intent.getExtras() == null) return; String title = intent.getStringExtra("NOTIFY_TITLE"); String content = intent.getStringExtra("NOTIFY_CONTENT"); if (title != null && content != null) { // 弹出AlertDialog new AlertDialog.Builder(this) .setTitle(title) .setMessage(content) .setPositiveButton("确定", (dialog, which) -> dialog.dismiss()) .show(); } }
方案二:如果必须用通知消息(带notification字段)
如果你的推送必须包含notification字段,那后台点击通知后,系统会把通知的内容放到MainActivity的Intent extras里,你可以直接在MainActivity里读取:
修改MainActivity的handleNotification方法即可:
private void handleNotification(Intent intent) { Bundle extras = intent.getExtras(); if (extras == null) return; // 读取通知消息的标题和内容(键名可能因Firebase版本略有差异,可打印extras查看) String title = extras.getString("notification_title"); String content = extras.getString("notification_body"); if (title != null && content != null) { new AlertDialog.Builder(this) .setTitle(title) .setMessage(content) .setPositiveButton("确定", null) .show(); } }
几个注意点
- Android 12及以上版本,创建PendingIntent必须添加
FLAG_IMMUTABLE或FLAG_MUTABLE,否则会抛出异常; - 通知渠道必须提前创建,否则Android O及以上版本不会显示通知;
- 如果App处于被杀死状态,点击通知会启动MainActivity,这时
onCreate会被调用;如果App在后台(已打开但不在前台),点击通知会触发onNewIntent,所以两个方法里都要处理Intent。
内容的提问来源于stack exchange,提问作者Sabin Pdel
相关产品推荐
相关产品推荐

