25

If FirstActivity is the root of the task, and it finishes itself and launches SecondActivity, then calling isTaskRoot() in SecondActivity immediately will return false, because the FirstActivity's finishing happens asynchronously and thus isn't done yet. Waiting for a second and then calling isTaskRoot() returns true.

public class FirstActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        finish();
        startActivity(new Intent(this, SecondActivity.class));
    }
}
public class SecondActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onResume() {
        super.onResume();
        ((TextView)findViewById(R.id.tv1))
                .setText("isTaskRoot() in onResume(): " + isTaskRoot());
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                ((TextView)findViewById(R.id.tv2))
                        .setText("isTaskRoot() after 1s: " + isTaskRoot());
            }
        }, 1000);
    }
}

screenshot of the result

Is there a way to …

  • (optimally) find out whether the activity will be the task root eventually, or,

  • (better than nothing) get some sort of notification/callback once the task is in its "final" state and thus isTaskRoot() will return the "truth"?

balpha
  • 50,022
  • 18
  • 110
  • 131
  • You could call isFinishing() on the Activity that was previously the task root to check if it is in the process of finishing. – Raghav Sood Jul 17 '13 at 14:16
  • @RaghavSood That only works if I know all activities in the stack, which I might not. – balpha Jul 17 '13 at 14:19
  • 1
    @balpha Hmm true. You could use `registerActivityLifecycleCallbacks()` on Application, if you are only going to support API Level 14 and higher (a.k.a., Android 4.0+). Or you could use one of the hacky unofficial snippets to get a list of all Activities in the stack – Raghav Sood Jul 17 '13 at 14:21
  • Actually, I'm not sure if there's an unofficial way to get the activities within a task. I know you can get a list of the tasks. – Raghav Sood Jul 17 '13 at 14:23
  • @RaghavSood I considered lifecycle activity callback, but since a) there may be multiple tasks that my app has activities in; and b) I'd like feedback immediately, and I'm not sure that `onActivityDestroyed` has a defined moment in the "task reordering cycle" when it's called (and thus could happen much later). – balpha Jul 17 '13 at 14:28
  • Well, this is about as API agnostic as it gets, but you could set a flag in your Application class right before you call `finish()` on any Activity, and just read that flag to see if you are finishing an Activity. – Raghav Sood Jul 17 '13 at 14:39
  • You can track such stuff yourself. Extend all your Activities from a special `Activity` class that maintains a static list of its instances. – S.D. Jul 20 '13 at 07:20
  • @S.D. That may work for my example case, but not in the general case when there may be other apps' activities in the task. I'm also not sure it works when the intent that starts the new activity has flags that modify the task. – balpha Jul 20 '13 at 07:54
  • Why don't you add the intent flag FLAG_ACTIVITY_NEW_TASK when launching SecondActivity? This way you properly define that the new activity will be part of a new task. – Markus Hi Jul 20 '13 at 19:08
  • @markushi_ I never said I want an activity *to be* task root. I want *to know whether it is or not.* – balpha Jul 20 '13 at 19:13
  • You could check the value in `onPostResume()`. http://developer.android.com/reference/android/app/Activity.html#onPostResume() I'm not sure if it will be any different, though. – marczych Jan 19 '14 at 04:23

2 Answers2

1

I've had a similar problem and I wanted tight control over exactly who the root activity is. In my case, the root could only be one of my own activities (not 3rd party ones), so I was able to use the following approach:

I extended the Application class, added a weak reference to an activity called currentRootActivity and added synchronized getter and setter.

Then I managed this state by myself when activities were created / destroyed. My use case was a little special because I was looking to replace one root with another, so I knew exactly where to reset my new state variable, but I'm pretty sure you can do the same.

I was even able to add this state logic in a shared base class for all of my activities. So this wasn't as disgusting as it sounds :)

As mentioned in the comments, the activity method isFinishing might also come in handy.

talkol
  • 12,564
  • 11
  • 54
  • 64
-3

Try:

Intent intent = new Intent(this, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

I expect that this will make SecondActivity the root activity.

cyanide
  • 3,885
  • 3
  • 25
  • 33
  • My question is not how to cause an activity to be root activity. My question is how to find out whether it is. Or rather, will eventually be. – balpha Dec 09 '13 at 06:33