一次完成所有活动


70

我有一个包含多个页面的应用程序,即多个活动,其中一些保持打开状态。

有没有办法一次关闭所有活动?


1
您能否更详细地描述您的应用/场景?通常不需要一次关闭所有活动。
fhucho

Answers:


132

每当您希望退出所有打开的活动时,都应按下一个按钮,该按钮将加载在应用程序启动时运行的第一个活动,然后清除所有其他活动,然后完成最后剩余的活动。为此,请在您的项目中应用以下代码

Intent intent = new Intent(getApplicationContext(), FirstActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);

上面的代码完成了除FirstActivity之外的所有活动。然后我们需要完成FirstActivity的Enter在Firstactivity的oncreate中输入以下代码

if (getIntent().getBooleanExtra("EXIT", false)) {
    finish();
}

就完成了...


1
但是此代码将使您的“后退”按钮不再正常运行。当您单击“返回”按钮时,它将关闭所有内容。那么如何处理/ @letsnurture?
gumuruh 2014年

怎么putExtra办?
用户

1
@letsnurture活动将保留在最近的应用程序列表中
Erum,2015年

1
启动Form Receiver时可以做什么。我尝试了与您相同的建议,但不起作用...任何建议?
CoDe 2015年

2
Intent intent = new Intent(getApplicationContext(),LoginActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent);
但丁

71

有一种finishAffinity()方法Activity可以完成当前活动和所有父活动,但仅在Android 4.1或更高版本中有效。

对于API 16+,请使用

finishAffinity();

对于较低版本(较低的Android 4.1),请使用

ActivityCompat.finishAffinity(YourActivity.this);

4
对于旧版Android,请使用ActivityCompat#finishAffinity()

23

我找到了最好的解决方案,它与API级别<11的设备兼容

Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);

此解决方案需要Android支持库


不错,这是最好的
lacas

工作
非常糟糕

22

对于API 16+,请使用

finishAffinity();

对于较低的,使用

ActivityCompat.finishAffinity(YourActivity.this)

1
请允许我在您的答案周围添加更多背景信息。仅代码的答案很难理解。如果您可以在帖子中添加更多信息,将对询问者和将来的读者都有帮助。
RBT

12

清除活动历史记录有三种解决方案。

1)您可以finish()在通过意图启动新活动时编写。

2)在Androidmanifest.xml文件中写入android:noHistory="true"所有<activity>标记,如果您打开的是新活动,并且那时没有编写finish(),则以前的活动总是会完成,因此在编写活动后,请使用此标记。

<activity
    android:name=".Splash_Screen_Activity"
    android:label="@string/app_name"
    android:noHistory="true">

</activity>

3)编写system.exit(0)退出应用程序的代码。


2
system.exit(0)用于退出应用程序:非常适合关闭Broadcastreceiver的活动
Akarsh M

但这不会导致将活动历史记录添加到堆栈中,而导致每次将其置于后台到前台时都会重新启动活动
Mr.G

11

您可以使用finishAffinity()将完成当前活动和所有父活动的方法。但这仅适用于API 16+

API 16+使用:

finishAffinity();

在API 16以下使用:

ActivityCompat.finishAffinity(this); //with v4 support library

要退出整个应用程序:

finishAffinity(); // Close all activites
System.exit(0);  // closing files, releasing resources

请不要针对多个问题发布相同的答案。发表一个好答案,然后投票/标记以将其他问题重复作为一个重复。如果问题不是重复的,请定制问题的答案。
Paul Roub

9

我在同一个问题上挣扎。打开关于页面并致电finish();从那里并没有关闭该应用程序,而是转到上一个活动,我想从About页面本身中关闭该应用程序。

这是为我工作的代码:

Intent startMain = new Intent(Intent.ACTION_MAIN); 
startMain.addCategory(Intent.CATEGORY_HOME); 
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(startMain); 
finish();

希望这可以帮助。


7

以下两个标志为我工作。他们将清除之前的所有活动并开始新的活动

  Intent intent = new Intent(getApplicationContext(), MyDetails.class);
  intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(intent);

希望这可以帮助。


6

没有其他答案对我有用。但是我进行了更多研究,终于得到了答案。

您实际上要求我关闭该应用程序。因此,添加以下代码:

finishAffinity();


这样完成所有活动吗?或者,仅当前活动?
GyuHyeon Choi

由于应用程序,所有活动正在运行。
Himanshu Sharma

4

如果您正在寻找的解决方案似乎更“书本上”且采用方法论设计(使用BroadcastReceiver),则最好查看以下链接:http : //www.hrupin.com/2011/10通过简单的调用/如何在您的android应用程序中完成所有活动

在该链接中显示的建议实施中,需要做一些细微的更改-为了启用暂停的活动,以便能够接收广播并对其进行处理,这意味着在重新启动应用程序时,还应该通过在打开的Activity的onCreate()方法中调用removeStickyBroadcast(Intent)方法来删除该粘性广播。

尽管上面提到的基于startActivity(...)的解决方案,乍一看-看起来非常好,优雅,简短,快速且易于实现-他们感到有些“错误”(开始一项活动-拥有所有可能只是为了杀死它而可能需要和涉及的开销和资源?...)



3

问题finishAffinity()在于,仅关闭当前任务中的活动,而带有singleInstancelaunchMode和其他任务中的活动仍处于打开状态,并在之后移至前台finishAffinity()。问题所在System.exit(0)在于您将使用所有后台服务和所有分配的内存来完成App流程,这可能导致不良的副作用(例如,不再接收通知)。

这是解决这两个问题的两种选择

  1. ActivityLifecycleCallbacks在需要的时候,你的应用程序类注册创建活动,并关闭它们:https://gist.github.com/sebaslogen/5006ec133243379d293f9d6221100ddb#file-myandroidapplication-kt-L10
  2. 在测试中,您可以使用ActivityLifecycleMonitorRegistryhttps : //github.com/sebaslogen/CleanGUITestArchitecture/blob/master/app/src/androidTest/java/com/neoranga55/cleanguitestarchitecture/util/ActivityFinisher.java#L15

这似乎是最好的答案
Laimiux

当今最好的答案是由于生命周期的活动,无需控制他们的状态或意图
lukassos

1

您可以存储一个布尔值标志,以表示是否应该完成所有活动(在共享首选项中更优选),然后onStart()每个活动的方法应类似于:

SharedPreferences pref=PreferenceManager.getDefaultSharedPreferences(this);
boolean needToDestroyFlag=pref.getBoolean("destroyFlag", false);
if(needToDestroyFlag)
{
    finish();
}else
{
    //...
}

显然,在需要完成所有活动(在当前活动中)之后,您可以像下面那样设置此标志,这样就可以在当前活动上调用finish()方法,这将终止当前活动并从堆栈中弹出活动一种,每个方法的onStart()方法都会执行并导致终止它:

SharedPreferences.Editor editor=PreferenceManager.getDefaultSharedPreferences(this).edit();
editor.putBoolean("destroyFlag", true);
editor.apply();

如果使用@letsnurture建议的方法,您将面临@gumuruh提出的问题。


感谢您的方法,它对我有所帮助。我使用静态类变量而不是共享首选项进行了类似的操作,这在整个应用程序生命周期中都存在。在每个活动的onResume中,调用super.onResume();。如果(ExitHelper.isExitFlagRaised){this.finish(); }。尽管它可能无法完成所有活动,但它确实完成了将自动恢复的活动。
凯文·李


1

您可以使用以下代码:

Intent i = new Intent(OldActivity.this, NewActivity.class);

i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

startActivity(i);

0

如果扎根:

Runtime.getRuntime().exec("su -c service call activity 42 s16 com.example.your_app");

0

关闭应用

Intent intent = new Intent(getApplicationContext(), Splash_Screen.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                intent.putExtra("EXIT", true);
                startActivity(intent);

将其放在打开的第一个活动的oncreate和onResume中。例如 在启动画面活动中

if (getIntent().getBooleanExtra("EXIT", false)) {
            this.finish();
            System.exit(0);
        }

0
in LoginActivity

@Override
    public void onBackPressed() {
        Intent startMain = new Intent(Intent.ACTION_MAIN);
        startMain.addCategory(Intent.CATEGORY_HOME);
        startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(startMain);
        finish();
        super.onBackPressed();
    }


0
@Override
    public void onBackPressed(){
        MaterialAlertDialogBuilder alert = new MaterialAlertDialogBuilder(BorrowForm.this, MyTheme);
        alert.setTitle("Confirmation");
        alert.setCancelable(false);
        alert.setMessage("App will exit. Data will not be saved. Continue?");
        alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast toast = Toast.makeText(BorrowForm.this, "App terminated.", Toast.LENGTH_SHORT);
                toast.getView().setBackgroundColor(Color.parseColor("#273036"));
                toast.setGravity(Gravity.CENTER_HORIZONTAL,0,0);
                TextView toastMessage=(TextView) toast.getView().findViewById(android.R.id.message);
                toastMessage.setTextColor(Color.WHITE);
                toast.show();
                finishAffinity();
            }
        });
        alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        alert.setCancelable(false);
        alert.show();
    }

-9

我是Java / android的入门者,可能是这个简单的解决方案对您有帮助

首先,创建静态类

public class ActivityManager {

    static Activity  _step1;
    static Activity _step2;
    static Activity _step3;

    public static void setActivity1(Activity activity)
    {
        _step1 = activity;
    }

    public static void setActivity2(Activity activity)
    {
        _step2 = activity;
    }

    public static void setActivity3(Activity activity)
    {
        _step3 = activity;
    }

    public static void finishAll()
    {
        _step1.finish();
        _step2.finish();
        _step3.finish();
    }

}

然后, 当您运行新活动时,保存指向您经理的链接(在步骤1中):

ActivityManager.setActivity1(this);
AddValuesToSharedPreferences();
Intent intent = new Intent(Step1.this, Step2.class);
startActivity(intent);

然后在最后一步完成所有操作:

 public void OkExit(View v) throws IOException {
        ActivityManager.finishAll();
    }

2
永远不要持有对活动的静态引用。活动使用相对较多的内存,当活动进入后台时应释放这些内存。只要进程还活着,就保持静态引用,这对应用程序而言将永远存在。作为开发人员和用户,这对您都不利。
Pijusn 2014年

全局变量是严重的反模式。
ezaquarii 2014年

可怕。绝不能保持对活动的全局引用。
PerracoLabs
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.