2

How can I click a notification, bring my app to the foreground if needed, and keep the stack as it was (even when the app went to the background)?

I have a NotificationClickActivity that is launched when the user clicks a notification.

When the notification is clicked, I have two possible scenarios:

  1. User is logged out from the app
  2. User is logged in.

In the first scenario, NotificationClickActivity starts the login process and receives the result. If OK, I launch MainActivity. The task is cleared so MainActivity is the only activity that I have in the task. I have no problems in this scenario.

In the second scenario NotificationClickActivity does this:

finish()  
startActivity(MainActivity.createIntent(this).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP).putExtra("notification", notification))

With the above code, if the app is already running (MainActivity is the root and top activity) and if on the background or in the foreground, I have no problems. MainActivity onNewIntent is called and I can do whatever I what with the notification. In this case, I dispatch the notification to a repository.

The problem I'm facing is when I have activities on top of MainActivity. Imagine the following stack:

MainActivity -> ActivityOne -> ActivityTwo -> ActivityN

With the code that I currently have if I click the notification the stack becomes:

MainActivity -> ActivityOne -> ActivityTwo -> ActivityN -> MainActivity

I want the stack to stay MainActivity -> ActivityOne -> ActivityTwo -> ActivityN but still pass the notification to MainActivity so it can be dispatched to the repository.

Any idea how can I achieve this?

I've been playing with the intent flags for some time but without success. Of course, I what this without any visible animations or whatever so that the user does not realize what is going on.

Favolas
  • 6,963
  • 29
  • 75
  • 127

2 Answers2

1

Think you're looking for FLAG_ACTIVITY_REORDER_TO_FRONT

.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP || FLAG_ACTIVITY_REORDER_TO_FRONT)

This will bring the activity to the top of the stack if its already running.

consider a task consisting of four activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then B will be brought to the front of the history stack, with this resulting order: A, C, D, B.

In the above example, if you want to go from A,B,C,D to A,B,C,D,B instead, then you need to make sure your activity supports multiple instances.

Suggest FLAG_ACTIVITY_SINGLE_TOP to be specified in android manifest for the activity instead. Then in your onNewIntent you should check if the user is logged in. If the user is not, you should launch the login process with startActivityForResult and handle the login result with onActivityResult.

This assumes your login can be initiated with an intent, which calls setResult with enough information for the caller to determine if the login was successful.

As for animations, I think you will have to use fragments and disable animations, or disable animations for the activity, and do custom transitions only when you want it. This may even not work with activities, since the OS/OEM defined transitions may just happen with activities regardless anyway, so you'll very likely have to make sure rest of the app is in the same activity and use fragments for navigation.


Madushan
  • 6,977
  • 31
  • 79
  • Thanks, but I don't want to reorder to front. Also, I don't have any problems when my user is logged out. I only have if he is logged in and if the stack is A, B, C, D. In this case, clicking the notification I want to keep the stack as A, B, C, D but: 1 - Pass info to A and 2 - Bring the app to the foreground if it's on the background. Another possibility would be to check whats the topmost activity. – Favolas Jun 20 '20 at 14:59
  • Right. Short answer is no. Only way to pass information to an activity is to bring it back from paused state, which means it starts, and comes to the front. I believe what you want is to update some state, which A can refresh upon its next 'resume'. For this, you can use a separate activity without any UI, which handles the intent and finish. As per bringing current activity to front, may be you can make your intent more generic. Set category, and package name, but don't specify the activity. Think this is what happens when you click launcher icon. That might work. – Madushan Jun 20 '20 at 15:05
0

This is not possible with this approach. If the current task contains MainActivity and also other activities on top of that, there is no way to send an Intent to MainActivity (without removing the activities on top of MainActivty) using startActivity or by launching an Activity.

If you need to get information to MainActivity then you need to use another mechanism to do this:

  • Send a broadcast Intent and have MainActivity listen for the broadcast
  • Use an event bus implementation
  • Use a "global variable" to pass this information between the 2 activities
David Wasser
  • 93,459
  • 16
  • 209
  • 274