如何检查活动是否是应用程序活动堆栈中的最后一个活动?


Answers:


116

更新(2015年7月):

由于getRunningTasks()已弃用,因此从API 21开始,最好遵循raukodraug 答案Ed Burnette的 一个(我希望第二个)。


可以使用ActivityManager检查当前任务及其堆栈。

因此,要确定一项活动是否为最后一项活动:

  • 在清单中请求android.permission.GET_TASKS权限。
  • 使用以下代码:

    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");
    }

请注意,以上代码仅在您具有单个任务时才有效。如果您的应用程序可能存在许多任务-您将需要检查其他taskList元素。阅读有关任务的更多信息任务和Back Stack



25
H9kDroid提出了正确的建议。所选答案是黑客。应该使用该isTaskRoot()方法以正确的方式进行操作。
苏菲安2014年

@Sufian特别在哪里破解?该代码具有逻辑性,并按预期使用的方式使用开放的android API(例如,应使用getRunningTasks来获取正在运行的任务,并且可能仅出于分析这些任务的目的而调用它)。get(0)的用法有据可查,并且逻辑上是“返回当前正在运行的任务的列表,最新的是依次执行的任务,第一个是较旧的任务”。
sandrstar 2015年

2
getRunningTasks()在API级别21中已弃用。–
gilchris

我可以为片段做同样的事情吗?如果是,那怎么办?请帮忙
Sagar Devanga 2015年

1
@ Mr.Drew看到@ raukodraug的最高票数
David Wasser

167

我将在这里发布@ H9kDroid的评论,作为有类似问题的人的最佳答案。

您可以使用isTaskRoot()来了解活动是否是任务的根。

我希望这有帮助


1
能否请您提供单行代码,以便清楚地说明如何使用isTaskRoot。谢谢。
Kaveesh Kanwal'Mar

18
@TheHunterif (isTaskRoot()) { // do something }
howettl

3
唯一的问题是,在<= 4.4上,我看到的行为与在> = 5.x中的行为不同。它似乎总是返回false。
chubbsondubs's

我认为您应该考虑将注释中提供的示例代码合并到答案中,以使将来的读者更轻松。
Isac '18

极好的答案。在我的情况下,如果用户在单击通知后单击该活动,则该活动可能是其根源
dave o grady

19

希望这对新手有帮助。根据以上对我来说很有效的答案,我也共享代码段,以使其易于实现。

解决方案:如果当前活动仅是您堆栈中的活动,并且我还处理其他情况(如果我在堆栈中有一些活动,则转到堆栈中的最后一个活动而不是打开新的自定义活动),则使用isTaskRoot()该方法返回true

在您的活动中

   @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();
        }

    }


5

尽管可能有一种方法可以做到这一点(请参阅其他答案),但我建议您不要这样做。普通的Android应用程序不需要知道是否要显示主屏幕。

如果您要保存数据,请将数据保存代码放入onPause()方法中。如果您试图为用户提供一种改变他们对现有应用程序的主意的方法,则可以截取Back键的上/下键和onBackPressed()方法,并向他们显示“您确定吗?” 提示。


1
只要用户还没有离开活动,我是否需要运行服务该怎么办?我无法捕获像onStop之类的任何功能,因为可以在屏幕关闭后调用这些功能。
迈克尔,

2
如果后台服务启动一个Activity,也许您想知道它是否是堆栈中唯一的Activity。
Matt W

4

跟踪此问题的一种方法是在启动新活动并检查标记是否存在时包括标记。

每当您开始新活动时,请插入标记:

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

然后您可以像这样检查它:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")

1
如果该活动被杀死并且重新构建了活动堆栈,则不起作用-每个活动都是按需进行的。
2013年

3

sandrstar解决方案使用的问题ActivityManager是:您需要获得许可才能以这种方式获取任务。我找到了一个更好的方法:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

Activity上堆栈底部应该得到百达这一类在默认情况下,而其他活动不应该得到它。
但是,即使在某些设备上失败,您也可以在启动时进行设置Activity

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);

如果从推送通知中打开活动怎么办?他们没有类别发布者
nbtk

我很确定答案的第二部分仍然适用。您可以将类别设置为意图中的提示。在这种情况下,可能是出于通知上下文的意图。除此之外,您还可以为此使用标志。看到这个链接的通知创作意图:stackoverflow.com/questions/13716723/...
A. Binzxxxxxx

不过,如果您最早的活动是MainActivity,现在又恢复了,那么您会收到推送通知,并使用CATEGORY_LAUNCHER设置“ pending”来打开,那么您将有2个与此类别相关的活动。虽然可能在不同的任务上
nbtk

我不确定它如何与通知一起使用。我从来没有像您在这里那样使用它们。我很确定有一种简单的方法可以做到这一点,但自2014年第一季度以来我就没有接触过android代码。也许您想在这种情况下使用第二类?还是一些标志?但是我想这样工作是很重要的。那么如何开始主要活动并添加某种元信息以打开正确的活动呢?
A. Binzxxxxxx'9

2

我为我的所有活动创建了一个基类,扩展了AppCompatActivity,它具有一个静态计数器:

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); }
}

到目前为止,这已经足够好了。而不管API版本如何。当然,这要求所有活动都扩展此基类-就我而言,它们就是这样做的。

编辑:我注意到一个实例,当计数器在应用程序完全退出之前下降到零时,这是当方向改变并且只有一个活动处于打开状态时。当方向更改时,活动被关闭并创建了另一个活动,因此onDestroyed上一个活动onCreate被调用,然后在使用更改的方向创建相同的活动时被调用。这种行为必须予以考虑;可以使用OrientationEventListener


0

Android实现了一个Activity栈,建议您在此处阅读。您似乎想要做的只是检索调用活动:getCallingActivity()。如果当前活动是您应用程序中的第一个活动,并且该应用程序是从主屏幕启动的,则它应该(我假设)返回null


9
这将不起作用,因为如果未通过startActivityForResult()启动活动,则getCallingActivity()将返回null。
H9kDroid 2011年

0

此处遗漏的一件事是“主页键”单击,当它被激活时,您无法从活动中检测到它,因此最好通过处理“返回键”的按下并移至所需的活动来以编程方式控制活动堆栈只是做必要的步骤。

另外,您不能确定是否可以通过将一些额外的数据预设为用于打开活动的意图来检测从“最近的活动”列表开始的活动,因为在这种情况下可以重复使用这些数据。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.