8

I encountered an interesting issue, where an Activity is created multiple times, even it is defined as a singleTask or a singelInstance Activity in the manifest. Here is how this can be reproduced. Say, in the main activity:

@Override
protected void onResume() {
    Intent i = new Intent(MainActivity.class, SingleActivity.class);
    startActivity(i);
}

in my SingleActivity, I have:

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    Log.i("SingleActivity", "onCreate " + System.identityHashCode(this));
    ...
}

and in the manifest, I have:

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

now, if I start the application, things seem OK, expect in one case: if I press the 'back' button while SingleActivity is in front, it navigates back to MainActivity, where MainActivity.onResume() will create another SingleActivity instance, instead of bringing forward the one that already exists. this is something I know because on the log, a different identity hash code is displayed.

the same seems to be true if the launch mode is singleTask.

the only workaround seems to be to override onBackPressed(), but that seems like an ugly solution.

I wonder what I'm doing wrong

Elltz
  • 10,730
  • 4
  • 31
  • 59
Ákos Maróy
  • 919
  • 2
  • 10
  • 19

2 Answers2

14

This is a problem of taskAffinity. Because you haven't specified taskAffinity in the manifest on either your MainActivity or your SingleActivity, these 2 activities have the same (default) taskAffinity. When you start an activity, Android checks the taskAffinity of the activity that you want to start. If it is the same as the taskAffinity of the root activity in your task, then it will ignore launchMode="singleInstance" or launchMode="singleTask" (because those launch modes would require Android to create a new task to launch the activity in) and start the activity in the current task.

Unfortunately, this isn't well documented, but taskAffinity takes precedence over launchMode.

If you really want a singleTask or singleInstance activity (which is usually not the right thing to do because it brings with it a whole mess of other nasty things that you are likely to get wrong), then you need to make sure that your singleInstance or singleTask activity has the following in the manifest in its <activity> definition:

android:taskAffinity=""

If you need more information, search StackOverflow or Google for "launchmode taskaffinity"

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • 1
    If the all activities have finished, the task'll be destoryed, so when re-start the activity, it'll re-create activity even if the activity has specified the `singleInstance` flag. – Autobots May 30 '14 at 10:33
  • What do you mean by "it brings with it a whole mess of other nasty things that you are likely to get wrong"? In my case, I am using launchMode="singleInstance" and android:taskAffinity="" for my Launcher app and everything is OK. – Pascal Jun 08 '18 at 09:37
  • 1
    @Pascal If you have multiple activities in your app, this gets complicated. Also if your app can be started by another app it gets complicated. In general, using `singleTask` or `singleInstance` causes more subtle behaviour problems than it solves. It is rarely necessary to use a special launch mode. Most people try using it to solve a problem that they don't really understand, in my experience. – David Wasser Jun 08 '18 at 11:59
  • OK. In my case I just do that in my Launcher and I have no problem with that. Thanks – Pascal Jun 08 '18 at 14:25
5

By default, pressing the BACK key finishes (destroys) the current activity and displays the previous activity to the user.

So, this is impossible to

instead of bringing forward the one that already exists

because no activity exists.

Waza_Be
  • 39,407
  • 49
  • 186
  • 260