Android点击通知打开指定Activity:后台关闭时跳转异常
解决应用关闭后点击通知跳转指定Activity的问题
问题核心:当应用处于后台或完全关闭状态时,Firebase的纯通知消息会由系统托盘直接处理,默认启动应用的启动Activity(即你的MainActivity),而非你在PushNotificationService中指定的BildirimGonder。要实现统一跳转,需要同时处理前台自定义通知和后台启动Activity的跳转逻辑。
解决方案步骤
1. 修改通知Intent的配置
在PushNotificationService的durumaBagli方法中,给跳转Intent添加标记参数和启动栈控制,确保参数能传递且栈行为符合预期:
private void durumaBagli(String baslik, String icerik) { NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 1. 创建跳转Intent并添加标记参数 Intent intent = new Intent(this, BildirimGonder.class); intent.putExtra("FROM_NOTIFICATION", true); // 标记这是从通知跳转的请求 // 控制Activity栈:清除上方栈顶,避免重复创建实例 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pendingIntent = PendingIntent .getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); // 原有通知构建代码不变... if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ String kanalid = "kanalId"; String kanalAd = "kanalAd"; String kanalTanim = "kanalTanim"; int kanalOnceligi = NotificationManager.IMPORTANCE_HIGH; NotificationChannel kanal = notificationManager.getNotificationChannel(kanalid); if (kanal == null){ kanal = new NotificationChannel(kanalid,kanalAd,kanalOnceligi); kanal.setDescription(kanalTanim); notificationManager.createNotificationChannel(kanal); } builder = new NotificationCompat.Builder(this,kanalid); builder.setContentTitle(baslik); builder.setContentText(icerik); builder.setSmallIcon(R.drawable.gurpinarlogom); builder.setAutoCancel(true); builder.setContentIntent(pendingIntent); }else { builder = new NotificationCompat.Builder(getApplicationContext()); builder.setContentTitle(baslik); builder.setContentText(icerik); builder.setSmallIcon(R.drawable.gurpinarlogom); builder.setAutoCancel(true); builder.setContentIntent(pendingIntent); builder.setPriority(Notification.PRIORITY_HIGH); } notificationManager.notify(1,builder.build()); }
2. 在启动Activity(MainActivity)中处理跳转逻辑
当应用关闭后点击通知,系统会先启动MainActivity,此时需要在MainActivity中检查Intent参数,自动跳转到目标页面:
public class MainActivity extends AppCompatActivity { private BottomNavigationView bottomNav; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bottomNav = findViewById(R.id.bottomNav); NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager() .findFragmentById(R.id.nav_host_fragment); NavigationUI.setupWithNavController(bottomNav, navHostFragment.getNavController()); getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#01A2D6"))); // 处理通知跳转逻辑 handleNotificationIntent(getIntent()); } // 处理Activity复用的情况(比如应用在后台时点击通知) @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); handleNotificationIntent(intent); } private void handleNotificationIntent(Intent intent) { if (intent != null && intent.getBooleanExtra("FROM_NOTIFICATION", false)) { // 跳转到目标Activity Intent targetIntent = new Intent(this, BildirimGonder.class); targetIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(targetIntent); // 可选:如果不需要保留MainActivity在栈中,调用finish() // finish(); } } public void setActionBarTitle(String title) { getSupportActionBar().setTitle(title); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar_menu, menu); return true; } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.action_iletisim: Intent mesajGonder = new Intent(getApplicationContext(), MesajGonder.class); startActivity(mesajGonder); Toast.makeText(this, "İletişim sayfası", Toast.LENGTH_SHORT).show(); return true; default: return super.onOptionsItemSelected(item); } } }
3. 确保推送消息包含数据字段(可选但推荐)
如果你的推送是纯通知消息(仅包含notification字段),后台状态下系统会直接处理,不会走到onMessageReceived。为了覆盖所有场景,建议推送时同时包含data字段,这样即使后台也能触发onMessageReceived处理:
示例推送JSON:
{ "notification": { "title": "推送标题", "body": "推送内容" }, "data": { "target_activity": "BildirimGonder" }, "to": "设备FCM令牌" }
然后在onMessageReceived中读取data字段,动态指定跳转目标:
@Override public void onMessageReceived(@NonNull RemoteMessage message) { String baslik = message.getNotification().getTitle(); String icerik = message.getNotification().getBody(); // 读取自定义数据 String targetActivity = message.getData().get("target_activity"); durumaBagli(baslik, icerik, targetActivity); } // 修改durumaBagli方法,接收目标Activity参数 private void durumaBagli(String baslik, String icerik, String targetActivity) { NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); Intent intent; // 根据data字段动态创建Intent if ("BildirimGonder".equals(targetActivity)) { intent = new Intent(this, BildirimGonder.class); } else { intent = new Intent(this, MainActivity.class); } intent.putExtra("FROM_NOTIFICATION", true); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); // 后续通知构建代码不变... }
关键原理说明
- 前台状态:通知由
PushNotificationService构建,PendingIntent直接指向目标Activity,点击后正常跳转。 - 后台/关闭状态:系统先启动启动Activity(MainActivity),通过检查Intent中的
FROM_NOTIFICATION标记,自动触发跳转到目标页面。
内容的提问来源于stack exchange,提问作者Revenge
相关产品推荐
相关产品推荐

