Launch activity from notification instantiating activity even if already there

2.6k Views Asked by At

My app has a background service which can run even if the app is destroyed.
The app has two activities: A, which is the main activity, and B, a settings activity.
The notification is created whenever the app goes to background.
If I am in A, go to home screen and launch the activity from the notification (with the intent to A), a new (duplicate) activity A will be created!
I would like to implement this logic:

if (launched from notification with app destroyed) {
    // this is the case where the service is running in background with the app destroyed
    create A;
} else {
    // don't create a new instance since A is already there. If current activity is B, stay in B (as if you pressed the launcher icon)
}

I currently use the following PendingIntent to launch the activity from notification:

PendingIntent launchActivity = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);

What is the correct way to implement the above logic, preferably programmatically. Thanks.

EDIT: FLAG_ACTIVITY_SINGLE_TOP does what I wanted, but there is still one problem: with this flag, the activity will not be created if and only if it's on top of the stack.
So, in the case the current stack is [MainActivity > Settings], since Settings is on top of the stack, the new stack will be [MainActivity > Settings > MainActivity], but what I wanted should be [MainActivity > Settings].
EDIT 2: basically, clicking on the notification should resume the app in the state it was.

2

There are 2 best solutions below

3
On BEST ANSWER

First of all, try to set PendingIntent flag to PendingIntent.FLAG_UPDATE_CURRENT instead of 0:

PendingIntent launchActivity = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

Then set android:launchMode="singleTop" for the Activity A (i.e. MainActivity) to avoid recreating it when it's opened:

<activity
    android:name=".MainActivity"
    ...
    android:launchMode="singleTop">
    ...
</activity>

Finally in the MainActivity, do the Intent handling in onCreate (when the Activity was destroyed and now created by clicking on notification) and onNewIntent method (when the Activity is created and we want to handle notification click).

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    handleIntent(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    if(intent.hasExtra("KEY_TO_EXTRA")){
        // ...
    }
}
1
On

You can open RedirectActivity instead of your own activity :

public class RedirectAcivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(this, HomeActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(intent);
        finish();
    }
}

And your pendingIntent will be like:

PendingIntent launchActivity = PendingIntent.getActivity(this, 0, new Intent(this, RedirectActivity.class), 0);