应用未启动时如何保留Intent中的Extras参数?
问题
我的应用通过MyFirebaseMessagingService接收通知,通知的Intent指向作为启动页的Login Activity,目的是让未登录用户先登录再查看通知内容。目前遇到的问题:
- 应用运行时,Intent的Extras能正常携带并转发至目标Activity;
- 应用未运行时,点击通知启动应用后,Intent的Extras丢失——Bundle对象存在但没有原参数。
以下是相关代码:
通知生成代码(MyFirebaseMessagingService)
public void sendCheckInNotification(Context context, String messageBody, String messageTypeIn, String messageIdIn) { generateRequestCode(messageIdIn); Log.i(TAG, "MyFirebaseMessagingService: " + messageTypeIn + " " + messageIdIn + " sendCheckInNotification: "); sendingActivity = "NewCheckInNotification"; Log.i(TAG, "MyFirebaseMessagingService sendCheckInNotification: sendingActivity= " + sendingActivity); Intent intent = new Intent (context, Login.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.putExtra("checkInTablePrimaryKey", assignedCheckInTablePrimaryKey); intent.putExtra("checkInTableFirebaseKey", checkInTableFirebaseKey); intent.putExtra("sendingActivity", sendingActivity); Log.i(TAG, "MyFirebaseMessagingService sendCheckInNotification: extras added= " + sendingActivity); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { pendingIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_IMMUTABLE); } else { pendingIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_ONE_SHOT); } String channelId = context.getResources().getString(R.string.new_check_in_channel_id); Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId) .setSmallIcon(R.drawable.ic_launcher) .setContentTitle(context.getResources().getString(R.string.check_in_notifications_header)) .setContentText(messageBody) .setStyle(new NotificationCompat.InboxStyle()) .setAutoCancel(true) .setContentIntent(pendingIntent) .setGroup(NEW_CHECK_IN_NOTIFICATION_GROUP) .setSound(defaultSoundUri); NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); // Since android Oreo notification channel is needed. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel(channelId, "New CheckingIn Notification", NotificationManager.IMPORTANCE_DEFAULT); notificationManager.createNotificationChannel(channel); } notificationManager.notify(requestCode /* ID of notification */, notificationBuilder.build()); }
Login Activity接收代码
extras = getIntent().getExtras(); Log.i(TAG, "Login onCreate: extras= " + extras); if (extras != null) { sendingActivity = extras.getString("sendingActivity"); Log.i(TAG, "Login onCreate: sendingActivity = " + sendingActivity); if (user != null) { Log.i(TAG, "Login onCreate: user is not logged in for notification"); if ((sendingActivity.equals("NewCheckInNotification")) || (sendingActivity.equals("PeepsWatcherUpdateNotification")) || (sendingActivity.equals("CheckInUpdateNotification")) || (sendingActivity.equals("CheckInLocationProvidedNotification")) || (sendingActivity.equals("NewCheckInLocationRequestNotification")) || (sendingActivity.equals("NewCheckInRequestNotification")) || (sendingActivity.equals("NewCheckInRequestUpdateNotification")) || (sendingActivity.equals("NewCheckInChatMessageNotification")) || (sendingActivity.equals("NewCheckInPicturesNotification"))) { Log.i(TAG, "Login onCreate: extras exist "); setIntentForNextActivity(); } else { Log.e(TAG, "Login onCreate: unknown sendingActivity for Intent " + sendingActivity); } } else { Log.i(TAG, "Login: user not logged in" ); String message = "You will be directed to your notification after logging in"; CustomToast newtoast = new CustomToast(context,message); newtoast.show(); } }
Manifest中Login Activity配置
<activity android:name="Login" android:exported="true" android:label="Peeps"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
解决方案
1. 修正PendingIntent的Flags配置
应用未启动时,系统可能复用旧的PendingIntent导致Extras丢失,需要调整Flags确保Extras被正确保留:
- Android M及以上版本,在
FLAG_IMMUTABLE基础上添加FLAG_UPDATE_CURRENT; - 低版本直接使用
FLAG_UPDATE_CURRENT替换FLAG_ONE_SHOT。
修改后的PendingIntent创建代码:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { pendingIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); } else { pendingIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); }
2. 调整Activity启动模式与Intent Flags
当前Login作为Launcher Activity,FLAG_ACTIVITY_SINGLE_TOP在应用未启动时作用有限,可调整Intent Flags或Manifest配置:
- 替换原有Intent Flags为
FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_NEW_TASK,确保启动时正确传递Intent; - 或在Manifest中给
Login设置android:launchMode="singleTask",避免重复创建实例并保证Intent传递。
修改Intent Flags示例:
Intent intent = new Intent(context, Login.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
3. 正确获取启动Intent
应用未启动时,系统可能传递Launcher的默认Intent而非通知Intent,需做适配:
- 若设置了
singleTask启动模式,重写onNewIntent()方法更新Intent并处理Extras; - 将Extras处理逻辑抽成独立方法,方便
onCreate()和onNewIntent()复用。
示例代码:
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); // 更新为最新的通知Intent handleExtras(getIntent().getExtras()); } private void handleExtras(Bundle extras) { if (extras != null) { sendingActivity = extras.getString("sendingActivity"); Log.i(TAG, "Login handleExtras: sendingActivity = " + sendingActivity); // 原有的判断与跳转逻辑 if (user != null) { // ... 后续处理 } else { // 未登录提示逻辑 } } }
4. 确保RequestCode唯一性
验证generateRequestCode(messageIdIn)生成的requestCode是唯一值,避免不同通知的PendingIntent被复用,导致Extras被覆盖。
内容的提问来源于stack exchange,提问作者GeorgeRussell
相关产品推荐
相关产品推荐

