How to check if an activity is the last one in the activity stack for an application?
Asked Answered
G

11

139

I want to know if user would return to the home screen if he exit the current activity.

Godard answered 12/5, 2011 at 9:15 Comment(1)
this might help: https://mcmap.net/q/168102/-activities-stackCattalo
S
124

UPDATE (Jul 2015):

Since getRunningTasks() get deprecated, from API 21 it's better to follow raukodraug answer or Ed Burnette one (I would prefer second one).


There's possibility to check current tasks and their stack using ActivityManager.

So, to determine if an activity is the last one:

  • request android.permission.GET_TASKS permissions in the manifest.
  • Use the following code:

    ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
    
    List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
    
    if(taskList.get(0).numActivities == 1 &&
       taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
        Log.i(TAG, "This is last activity in the stack");
    }
    

Please note, that above code will be valid only if You have single task. If there's possibility that number of tasks will exist for Your application - You'll need to check other taskList elements. Read more about tasks Tasks and Back Stack


Saiff answered 5/6, 2011 at 9:48 Comment(8)
H9kDroid has made a correct suggestion. The selected answer is a hack. One should do it the right way using the isTaskRoot() method.Vetiver
@Vetiver where is it hack particularly? The code is logical and uses open android APIs in the way they intended to be used (e.g. getRunningTasks should be used to get running tasks and one might want to call it only with the purpose to analyze these tasks). Usage of get(0) is well documented and logical 'Return a list of the tasks that are currently running, with the most recent being first and older ones after in order'.Saiff
getRunningTasks() is deprecated in API level 21.Tolland
Can i do the same thing for fragments. If yes then how ? Please helpAdrenocorticotropic
@SagarDevanga hm, probably you can try to use developer.android.com/reference/android/app/… , but it will require you to add every fragment to backstack. Otherwise, you can keep some kind of global counter of fragments in Application class for example.Saiff
Good info but you should put the update notice at the top so it's the first thing people seeHerder
Now that GET_TASKS is depreciated, how can we get this same functionality?Custodian
@Custodian see the highest voted answer from @ raukodraugHoarfrost
L
189

I'm going to improve on the comment of @H9kDroid as the best answer here for people that have a similar question. (Original link)

You can use isTaskRoot() to know whether the activity is the root of a task.

Liesa answered 27/3, 2013 at 16:35 Comment(7)
can you please provide the single line of code so that its clear on how to use isTaskRoot. Thanks.Marked
@TheHunter if (isTaskRoot()) { // do something }Lorraine
The only problem is that on <=4.4 I'm seeing it do different behavior than in >= 5.x. It seems to always return false.Daria
I think you should consider incorporating the sample code provided in the comments into the answer, to make it easier for future readers.Bevan
excellent answer. in my case after the user clicks on a notification the activity might be the root if they closed the application beforeAnikaanil
As per the android docs, Single task activity is created in a new task and this activity is pushed as the root of the task. But I see in Single task activity this isTaskRoot() method is coming as false. Can anyone help me understand this?Phosphorism
isTaskRoot returns false even in onResumeThresathresh
S
124

UPDATE (Jul 2015):

Since getRunningTasks() get deprecated, from API 21 it's better to follow raukodraug answer or Ed Burnette one (I would prefer second one).


There's possibility to check current tasks and their stack using ActivityManager.

So, to determine if an activity is the last one:

  • request android.permission.GET_TASKS permissions in the manifest.
  • Use the following code:

    ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
    
    List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
    
    if(taskList.get(0).numActivities == 1 &&
       taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
        Log.i(TAG, "This is last activity in the stack");
    }
    

Please note, that above code will be valid only if You have single task. If there's possibility that number of tasks will exist for Your application - You'll need to check other taskList elements. Read more about tasks Tasks and Back Stack


Saiff answered 5/6, 2011 at 9:48 Comment(8)
H9kDroid has made a correct suggestion. The selected answer is a hack. One should do it the right way using the isTaskRoot() method.Vetiver
@Vetiver where is it hack particularly? The code is logical and uses open android APIs in the way they intended to be used (e.g. getRunningTasks should be used to get running tasks and one might want to call it only with the purpose to analyze these tasks). Usage of get(0) is well documented and logical 'Return a list of the tasks that are currently running, with the most recent being first and older ones after in order'.Saiff
getRunningTasks() is deprecated in API level 21.Tolland
Can i do the same thing for fragments. If yes then how ? Please helpAdrenocorticotropic
@SagarDevanga hm, probably you can try to use developer.android.com/reference/android/app/… , but it will require you to add every fragment to backstack. Otherwise, you can keep some kind of global counter of fragments in Application class for example.Saiff
Good info but you should put the update notice at the top so it's the first thing people seeHerder
Now that GET_TASKS is depreciated, how can we get this same functionality?Custodian
@Custodian see the highest voted answer from @ raukodraugHoarfrost
M
47

Hope this will help new beginners, Based above answers which works for me fine, i am also sharing code snippet so it will be easy to implement.

solution : i used isTaskRoot() which return true if current activity is only activity in your stack and other than i also handle case in which if i have some activity in stack go to last activity in stack instead of opening new custom one.

In your activity

   @Override
    public void onBackPressed() {

        if(isTaskRoot()){
            startActivity(new Intent(currentActivityName.this,ActivityNameYouWantToOpen.class));
            // using finish() is optional, use it if you do not want to keep currentActivity in stack
            finish();
        }else{
            super.onBackPressed();
        }

    }
Melaniemelanin answered 29/3, 2019 at 8:45 Comment(0)
F
17

there is an easiest solution to this, you can use isTaskRoot() in your activity

Finegrain answered 28/7, 2015 at 15:36 Comment(0)
T
5

One way to keep track of this is to include a marker when you start a new activity and check if the marker exists.

Whenever you start a new activity, insert the marker:

newIntent=new Intent(this, NextOne.class);
newIntent.putExtra(this.getPackageName()+"myself", 0);
startActivity(newIntent);

And you can then check for it like this:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")
Tva answered 3/6, 2011 at 1:15 Comment(1)
Doesn't work if the activity gets killed and the activity stack is reconstructed - each activity by demand.Meld
P
5

While there may be a way to achieve this (see other answers) I would suggest that you shouldn't do that. Normal Android applications shouldn't need to know if the Home screen is about to display or not.

If you're trying to save data, put the data saving code in your onPause() method. If you're trying to give the user a way to change their mind about existing the application, you could intercept the key up/down for the Back key and the onBackPressed() method and present them with an "Are you sure?" prompt.

Pyramid answered 8/6, 2011 at 21:45 Comment(2)
How about if I need a service running as long as the user hasn't left the activity? I can't trap any of the functions like onStop because these could be called after the screen is turned off.Trackman
If a background service launches an Activity, perhaps you'd like to know whether or not that's the only Activity on the stack.Ward
F
2

The Problem with sandrstar's solution using ActivityManager is: you need a permission to get the tasks this way. I found a better way:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

The Activity on the Stack bottom should allways get this category by default while other Activities should not get it.
But even if this fails on some devices you can set it while starting your Activity:

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);
Finochio answered 29/1, 2014 at 22:21 Comment(4)
What if the activity is opened from push notification? They don't have the CATEGORY LAUNCHERStagecoach
I am quite sure the second part of my answer still applies. You can set the category as a hint in the intent. In this case maybe in the intent of your notification context. Other than that you might also use flags for this. see this link for a notification creation with intent: #13717223Finochio
Still, If your oldest activity is MainActivity and now it is resumed, and then you receive push notification and you set the pendingIntent to open with CATEGORY_LAUNCHER, then you'll have 2 activities with this category. Probably on different tasks thoughStagecoach
I am not exactly sure how it works with notifications. I never used them like you do it here. I am quite sure there is a easy way to do it with this approach but I did not touch android code since Q1 2014. Maybe you want to use a second category for this case? Or some flag? But I guess its ment to work like this. How about starting the main activity and adding some kind of meta info to open the correct activity then?Finochio
S
2

I've created a base class for all my activities, extending the AppCompatActivity, and which has a static counter:

public abstract class BasicActivity extends AppCompatActivity {
    private static int activityCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ++activityCounter;
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        --activityCounter;
        if(activityCounter==0) {
            // Last instance code...
        }
    }

    public boolean isLastInstance() { return (activityCounter==1); }
}

This has worked well enough, so far; and regardless of API version. It requires of course that all activities extends this base class - which they do, in my case.

Edit: I've noticed one instance when the counter goes down to zero before the app completely exits, which is when the orientation is changed and only one activity is open. When the orientation changes, the activity is closed and another is created, so onDestroyed is called for the last activity, and then onCreate is called when the same activity is created with the changed orientation. This behaviour must be accounted for; OrientationEventListener could possibly be used.

Swetiana answered 2/10, 2016 at 0:31 Comment(0)
B
0

Android implements an Activity stack, I suggest you read about it here. It looks like all you want to do though is retrieve the calling activity: getCallingActivity(). If the current activity is the first activity in your application and the application was launched from the home screen it should (I assume) return null.

Bowerman answered 3/6, 2011 at 1:57 Comment(1)
That will not work since getCallingActivity() will return null if the activity was not started via startActivityForResult().Tva
W
0

The one thing that missed here, is the "Home key" click, when activated, you can't detect this from your activity, so it would better to control activity stack programmatically with handling "Back key" press and moving to required activity or just doing necessary steps.

In addition, you can't be sure, that starting your activity from "Recent Activity" list can be detected with presetting some extra data into intent for opening activity, as it being reused in that case.

Wen answered 9/6, 2011 at 13:28 Comment(0)
C
0
if (activity.isTaskRoot){
            toolbar.setNavigationOnClickListener{
                activity.startActivity(Intent(activity,HomeActivity::class.java))
            }
        }

**kotlin version of this code **

Checked answered 30/3, 2023 at 8:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.