Home » Android » Intent – if activity is running, bring it to front, else start a new one (from notification)

Intent – if activity is running, bring it to front, else start a new one (from notification)

Posted by: admin November 29, 2017 Leave a comment

Questions:

My app has notifications, which – obviously – without any flags, start a new activity every time so I get multiple same activities running on top of each other, which is just wrong.

What I want it to do is to bring the activity specified in the notifications pending intent, to the front if it is already running, otherwise start it.

So far, the intent/pending intent for that notification I have is

private static PendingIntent prepareIntent(Context context) {
    Intent intent = new Intent(context, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

    return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

and weirdly, it sometimes works, sometimes it doesn’t… I feel like I’ve already tried every single combination of flags.

Answers:

You can use this:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

which will work similar to "singleInstance" but it won’t have that weird animation.

Questions:
Answers:

I think the best way to do it and in a simple manner is to start the activity normally, but set that activity in the manifest with the singleInstance property. With this you practically approach both issues you are having right now, by bringing the activity to the front all the time, and letting the OS automatically create a new one if no activity exists or bring to the front the currently existing activity (thanks to the singleInstance property).

This is the way an activity is declared as a single instance:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleInstance"/>

Also to avoid a choppy animation when launching through singleInstance, you could use instead “singleTask”, both are very similar but the difference is explained here as per Google’s documentation:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

singleInstance is the same as “singleTask”, except that the system
doesn’t launch any other activities into the task holding the
instance. The activity is always the single and only member of its
task.

Hope this helps.

Regards!

Questions:
Answers:

I think what you need is in singleTop Activity, rather than a singleTask or singleInstance.

<activity android:name=".MyActivity"
          android:launchMode="singleTop"
          ...the rest... >

What the documentation says does perfectly suit your needs:

[…] a new instance of a “singleTop” activity may also be created to handle
a new intent. However, if the target task already has an existing
instance of the activity at the top of its stack, that instance will
receive the new intent (in an onNewIntent() call); a new instance is
not created. In other circumstances — for example, if an existing
instance of the “singleTop” activity is in the target task, but not at
the top of the stack, or if it’s at the top of a stack, but not in the
target task — a new instance would be created and pushed on the stack.

On top of that (no pun intended), I had exactly the same need as you. I tested all the launchMode flags to figure out how they actually behave in practice and as a result singleTop is actually the best for this: no weird animation, app displayed once in the recent applications list (unlike singleInstance that displays it twice due to the fact it doesn’t allow any other Activity to be part of its task), and proper behavious regardless the target Activity already exists or not.

Questions:
Answers:

Since you say you want to start your activity if it’s not started already, maybe you wouldn’t mind restarting it. I tested a ton of suggestions and flag combinations for the intent as well, this will always bring the activity you need to the front, though it won’t keep any state previously associated with it.

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);

API11+ only.

Questions:
Answers:

I tried this, and it worked even though the IDE was complaining about the code

Intent notificationIntent = new Intent(THIS_CONTEXT, MainActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    PendingIntent intent = PendingIntent.getActivity(THIS_CONTEXT, 0, notificationIntent, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(THIS_CONTEXT)
            .setSmallIcon(R.drawable.cast_ic_notification_0)
            .setContentTitle("Title")
            .setContentText("Content")
            .setContentIntent(intent)
            .setPriority(PRIORITY_HIGH) //private static final PRIORITY_HIGH = 5;
            .setAutoCancel(true)
            /*.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS)*/;
    NotificationManager mNotificationManager = (NotificationManager) THIS_CONTEXT.getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(0, mBuilder.build());

Questions:
Answers:

I know it is old, but nothing from the above were fitting to my application.

Without changing manifests and other configuration, here is the code to bring your app back to front – or opening it when it is closed

Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
notificationIntent.setPackage(null); // The golden row !!!
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);