Android点击通知(PendingIntent)打开错误Activity的技术求助
这个问题我之前也踩过坑,核心原因是FCM通知消息的处理逻辑在应用不同状态下完全不一样:
当你的应用处于前台/后台时,onMessageReceived会被正常触发,你通过sendNotification创建的通知用了自定义的PendingIntent,所以点击能正确打开IntroNoti。但当应用完全关闭(进程被杀死)时,如果FCM消息是通知类型(也就是payload里包含notification字段),系统会直接接管通知的展示,这时候点击通知会默认打开你的启动页(Splash Activity),根本不会走你在onMessageReceived里设置的PendingIntent逻辑。
下面给你几个可行的解决方案,按推荐程度排序:
方案1:改用FCM数据消息(最推荐)
让后端发送纯数据消息(payload里只包含data字段,不要notification字段),这样不管应用处于什么状态,onMessageReceived都会被触发,你可以完全自定义通知和跳转逻辑,不受系统默认行为干扰。
修改你的sendNotification方法,从remoteMessage.getData()里获取通知内容:
private void sendNotification(RemoteMessage remoteMessage) { // 从data字段提取通知标题和内容 String title = remoteMessage.getData().get("title"); String body = remoteMessage.getData().get("body"); Intent intent = new Intent(this, IntroNoti.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); // 把通知附带的数据传递给目标Activity intent.putExtras(remoteMessage.getData()); // 注意添加FLAG_IMMUTABLE适配Android 12及以上版本 PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); int icon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? R.drawable.ic_launcher: R.mipmap.ic_launcher; NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(icon) .setContentTitle(title) .setContentText(body) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, notificationBuilder.build()); }
方案2:在启动页(Splash Activity)中处理跳转
如果没法修改后端的消息发送格式,那可以在你的Splash Activity里加一层判断:如果是从FCM通知点击进来的,就直接跳转到IntroNoti,跳过原本的启动逻辑。
在Splash的onCreate方法里添加:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); // 检查是否是从FCM通知跳转过来的 Intent incomingIntent = getIntent(); if (incomingIntent != null && incomingIntent.getExtras() != null) { // 可以根据通知里的特定参数判断是否需要跳转,比如检查是否有"target_page"之类的字段 Intent targetIntent = new Intent(this, IntroNoti.class); targetIntent.putExtras(incomingIntent.getExtras()); startActivity(targetIntent); finish(); // 直接关闭Splash页,不让它走后续逻辑 return; } // 原来的Splash初始化逻辑,比如跳转到主页 // ... }
方案3:使用TaskStackBuilder构建正确的任务栈
如果你想保留通知消息的发送方式,也可以用TaskStackBuilder来构建符合预期的任务栈,确保应用关闭时点击通知能直接打开目标Activity。
修改sendNotification里的PendingIntent创建部分:
Intent intent = new Intent(this, IntroNoti.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 用TaskStackBuilder构建包含父Activity的任务栈 TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); stackBuilder.addNextIntentWithParentStack(intent); // 同样要加FLAG_IMMUTABLE适配高版本 PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
这个方案需要你在Manifest里给IntroNoti设置正确的父Activity,比如:
<activity android:name=".IntroNoti"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".SplashActivity"/> </activity>
内容的提问来源于stack exchange,提问作者Anto

