According to this thread on StackOverflow, "Android remembers the intent that was used to launch it". The problem described there is exactly what I'm going through:
When the app is launched for the first time from a
Notification
, this can mess things up. You launch the app from aNotification
and Android remembers theIntent
used (from theNotification
), when you later launch the app (again from aNotification
), android matches theIntent
in theNotification
with theIntent
used to launch the app for the first time, and thinks you want to bring the existing app task from the background to the foreground.
The problem: I don't understand why Android thinks that the Intent is the same. While the activity is the same, the intent has completely different extras.
When I add flags to the intent, I'm able to fix this issue. Like for example:
Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK
But my goal is to keep the back stack, which it doesn't using these flags of course.
It's a webview app with some additional screens.
The issue only exists when the app is launched through a notification. When I launch it myself and put it to the background, everything works as I wish.
Scenario
"openLink" =
https://something.com/one
"openLink" =
https://something.com/two
What I want:
How it is right now:
My code:
val pendingIntent = PendingIntent.getActivity(
baseContext,
notificationId,
newIntent,
PendingIntent.FLAG_IMMUTABLE
)
notificationBuilder = notificationBuilder.setContentIntent(pendingIntent)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(notificationId, notificationBuilder.build())
notificationId is unique. extras of newIntent are unique. I tried every flag there is I believe. MainActivity (which has the webview) has launchMode "singleTop", but of course I tried without setting a launchMode.
Further observations:
TaskStackBuilder
, because that doesn't keep the back stack. It just allows you to build your own back stack (impossible with webview)Your problem is that when the user taps on not1, Android launches the app with MainActivity
and remembers that the app was launched with MainActivity
.
When the user taps on not3, the Intent
in the Notification
has MainActivity
, which matches the Intent
that was used to launch the app initially. (Note: Android doesn't compare "extras" when comparing Intent
s.), so Android thinks that you want to bring the existing task containing the app forward from the background, which it does. In this case it doesn't create a new instance of MainActivity
, it doesn't call onNewIntent()
, it just brings the existing task (in whatever state it was in) to the foreground.
This is the same behaviour as when you are running an app, press HOME, press that app's icon again. Android thinks you want to return to the app, so it just brings it forward from the background.
Solution:
Add an ACTION to the Intent
that you put in the Notification
. Set the ACTION to some random string so that it is always unique whenever you create the Notification
.
This will ensure that whenever a user taps a Notification
to launch the app, the Intent
will not match the Intent
that was used to launch the app initially. Android will then bring the app forward from the background (if it is in the background), create a new instance of the Activity
and put that on the task stack.