Java 使用通知打开Android应用程序&;getLaunchIntentForPackage不';不要进行任何活动

Java 使用通知打开Android应用程序&;getLaunchIntentForPackage不';不要进行任何活动,java,android,android-notifications,android-pendingintent,launch,Java,Android,Android Notifications,Android Pendingintent,Launch,我使用Firebase(FCM)向用户显示推送通知,我遇到了一个奇怪的问题 我的代码适用于以下场景(使用FirebaseMessagingService): 前台应用程序-在onReceive()中接收数据并在应用程序内显示弹出窗口 后台应用程序-在onReceive()中接收数据并为用户显示通知。如果单击此按钮,应用程序将返回到前端在LauncherActivity中接收到此操作的意图,然后调用finish(),该调用会将我带到已打开的任何活动。 应用程序完全关闭-与背景相同。在调用该应用程

我使用Firebase(FCM)向用户显示推送通知,我遇到了一个奇怪的问题

我的代码适用于以下场景(使用FirebaseMessagingService):

  • 前台应用程序-在onReceive()中接收数据并在应用程序内显示弹出窗口
  • 后台应用程序-在onReceive()中接收数据并为用户显示通知。如果单击此按钮,应用程序将返回到前端在LauncherActivity中接收到此操作的意图,然后调用finish(),该调用会将我带到已打开的任何活动。
  • 应用程序完全关闭-与背景相同。在调用该应用程序的finish()之前,将启动该应用程序,并在LauncherActivity中处理意图
这里是它变得有趣的地方:

  • 应用程序完全关闭->通过通知打开它(在LauncherActivity中接收到意图)->将应用程序置于后台并发送另一个通知->单击此通知时,LauncherActivity将被完全忽略(不再调用onCreate),我将直接进入我已经拥有的任何活动。此处的意图没有额外内容或类别。 在这种特定情况下,为什么要绕过Launcher活动?请记住,如果应用程序最初是正常启动的(而不是通过单击通知),那么这样做很好

如果有任何想法,我将不胜感激。谢谢。

当你第一次启动一个应用程序时,Android会记住用来启动它的
意图。通常,当您从主屏幕启动应用程序时,这是一个包含ACTION=MAIN和CATEGORY=LAUNCHER的
Intent
。如果你的应用程序随后进入后台(无论出于何种原因),用户随后点击主屏幕上的图标,则使用相同的启动
Intent
。Android将此与第一次启动应用程序时使用的
意图
相匹配,如果这些匹配,Android不会启动新的
活动
,它只会将包含应用程序的任务从后台带到前台,无论它移到后台时处于何种状态。在正常情况下,这正是您想要的(以及用户期望的)行为

然而,当应用程序第一次从
通知启动时,这可能会把事情搞砸。在你的情况下,这就是你所看到的。您从
通知
启动应用程序,当您稍后启动应用程序时(再次从
通知
),Android会记住所使用的
意图(从
通知
),android将
通知中的
意图
与用于首次启动应用程序的
意图
相匹配,并认为您希望将现有应用程序任务从后台转移到前台


有几种方法可以解决这个问题,具体取决于您想要的行为。最好不要从
通知中启动root
活动(ACTION=MAIN,CATEGORY=LAUNCHER)。相反,启动一个不同的
活动
,并让该
活动
确定下一步应该做什么(即:重定向到根
活动
或其他内容,具体取决于应用程序的状态)。您还应该在您放入
通知的
意图上设置
无历史记录
从最近事件中排除
标志。这将确保Android不会将此
意图
记为启动应用程序的意图。

当您第一次启动应用程序时,Android会记住用于启动应用程序的
意图。通常,当您从主屏幕启动应用程序时,这是一个包含ACTION=MAIN和CATEGORY=LAUNCHER的
Intent
。如果你的应用程序随后进入后台(无论出于何种原因),用户随后点击主屏幕上的图标,则使用相同的启动
Intent
。Android将此与第一次启动应用程序时使用的
意图
相匹配,如果这些匹配,Android不会启动新的
活动
,它只会将包含应用程序的任务从后台带到前台,无论它移到后台时处于何种状态。在正常情况下,这正是您想要的(以及用户期望的)行为

然而,当应用程序第一次从
通知启动时,这可能会把事情搞砸。在你的情况下,这就是你所看到的。您从
通知
启动应用程序,当您稍后启动应用程序时(再次从
通知
),Android会记住所使用的
意图(从
通知
),android将
通知中的
意图
与用于首次启动应用程序的
意图
相匹配,并认为您希望将现有应用程序任务从后台转移到前台


有几种方法可以解决这个问题,具体取决于您想要的行为。最好不要从
通知中启动root
活动(ACTION=MAIN,CATEGORY=LAUNCHER)。相反,启动一个不同的
活动
,并让该
活动
确定下一步应该做什么(即:重定向到根
活动
或其他内容,具体取决于应用程序的状态)。您还应该在您放入
通知的
意图上设置
无历史记录
从最近事件中排除
标志。这将确保Android不会记住这个
意图
是启动应用程序的那一个。

我使用了一个单独的活动,我从FLAG\u activity\u NEW\u TASK,FLAG\u ACT开始
Intent mainIntent = getPackageManager().getLaunchIntentForPackage(getPackageName()); 
if (mainIntent != null) {
    mainIntent.addCategory(NOTIFICATION_CATEGORY);
    mainIntent.putExtra(.........);
}
PendingIntent pendingMainIntent = PendingIntent.getActivity(this, SERVICE_NOTIFICATION_ID, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, context.getString(R.string.default_notification_channel_id));
notificationBuilder.setContentIntent(pendingMainIntent);
//.....icon, color, pririty, autoCancel, setDefaults, setWhen, setShowWhen, contentText, setStyle

NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(
            getString(R.string.default_notification_channel_id),
            getString(R.string.default_notification_channel),
            NotificationManager.IMPORTANCE_HIGH
        );
        notificationManager.createNotificationChannel(channel);
        notificationBuilder.setChannelId(getString(R.string.default_notification_channel_id));
    }
    notificationManager.notify(SERVICE_NOTIFICATION_ID, notificationBuilder.build());
}