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



我想知道如果用户退出当前活动,他是否会返回主屏幕。

我将改进@H9kDroid的评论,作为有类似问题的人的最佳答案。(原文链接)

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

更新(2015 年 7 月):

由于getRunningTasks()被弃用,从API 21开始,最好遵循raukodraug答案或Ed Burnette答案(我更喜欢第二个)。


可以使用活动管理器检查当前任务及其堆栈。

因此,要确定活动是否是最后一个活动,请执行以下操作:

  • 在清单中请求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 元素。阅读有关任务任务和后退堆栈的更多信息


希望这对新的初学者有所帮助,基于上述对我有用的答案,我也在共享代码片段,以便易于实现。

解决方案:我使用了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();
        }
    }
有一个

最简单的解决方案,你可以使用isTaskRoot()在您的活动中

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

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

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

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

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

虽然可能有一种方法可以实现这一点(见其他答案),但我建议你不应该这样做。普通的Android应用程序不需要知道主屏幕是否即将显示。

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

我已经为所有活动创建了一个基类,扩展了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。

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

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

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

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

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

这里遗漏的一件事是"主页键"单击,激活后,您无法从活动中检测到这一点,因此最好通过处理"后退键"以编程方式控制活动堆栈按下并移动到所需的活动或只是执行必要的步骤。

此外,您不能确定,通过将一些额外的数据预设为打开活动的意图,可以检测到从"最近活动"列表中启动活动,因为在这种情况下会重复使用。

if (activity.isTaskRoot){
            toolbar.setNavigationOnClickListener{
                activity.startActivity(Intent(activity,HomeActivity::class.java))
            }
        }

此代码的 Kotlin 版本**

最新更新