如何以编程方式退出android应用程序


321

我找到了一些用于以编程方式退出Android应用程序的代码。通过在onDestroy()中调用以下任何代码,它将完全退出应用程序吗?

  1. System.runFinalizersOnExit(true)
    (要么)
  2. android.os.Process.killProcess(android.os.Process.myPid());

单击退出按钮后,我不想在后台运行我的应用程序。请建议我可以使用这些代码中的任何一个退出我的应用程序吗?如果可以,我可以使用哪个代码?这是退出Android应用程序的好方法吗?




使用'System.exit(0);' 当您确实要退出该应用程序时。向用户显示一条消息后,我已经解决了一个不可恢复的错误。如果需要,您甚至可以使用AlarmManager自动重新启动应用程序。请参阅:blog.janjonas.net/2010-12-20/…–
某处某人

Answers:


396

从API 16开始,您可以使用finishAffinity方法,该方法似乎非常接近通过其名称和Javadoc描述来关闭所有相关活动:

this.finishAffinity();

完成此活动以及当前任务中紧接其下的所有具有相同关联性的活动。通常,当可以将应用程序启动到另一个任务上(例如从它了解的内容类型的ACTION_VIEW启动)并且用户已使用向上导航切换到当前任务并切换到其自己的任务时,通常使用此方法。在这种情况下,如果用户向下导航到第二个应用程序的任何其他活动,则应将所有这些活动从原始任务中删除,作为任务切换的一部分。

请注意,完成此操作后,您无法将结果传递到上一个活动,如果尝试这样做,将引发异常。


从API 21开始,您可以使用非常相似的命令

finishAndRemoveTask();

完成此任务中的所有活动,并将其从最近任务列表中删除。


28
绝对是正确的答案!使用结束应用程序不是一个好的解决方案System.exit(0);。谢谢您的回答!终于,我找到了一个不错的解决方案。
安东尼奥

4
您是否知道API 14还有其他解决方案?谢谢
脚本小猫2015年

2
您可以在关闭应用程序时或在活动lifcycle内部单独完成()每个活动。
2013年

3
警告!this.finishAffinity()关闭应用程序,将其从内存中删除,因此您不会收到推送消息,依此类推。
Tincho825 '18

7
该解决方案在99%的情况下都有效。但是,它不会破坏进程,因此例如Dagger将不会被清除。在极少数情况下,需要终止进程是System.exit(0)唯一对我有用的解决方案。
斯拉夫(Slav)

155
getActivity().finish();
System.exit(0);

这是退出应用程序的最佳方法。

对我来说最好的解决方案。


是的,效果很好!必须从MainActivity调用它才能使其正常工作!
mz87 2014年

完美的解决方案。无需终止进程,因为Android最了解内存管理。但是,这提供了完成活动以及为用户方便退出应用程序的解决方案。
IAmTheSquidward

确实是完美的解决方案。解决了很多问题。谢谢。
superuserdo 2015年

26
我认为这不是一个好的解决方案。不应该使用来完成程序System.exit(0);。正确的解决方案是@sivi发布的(他的回答在上面)
Antonio

13
这不是解决方案,如果您有很多活动
它就行不通

45

finishAffinity();

System.exit(0);

如果仅在finishAffinity();不使用System.exit(0);应用程序的情况下退出使用,但分配的内存仍将在电话中使用,那么...如果您希望彻底清除应用程序,请同时使用它们。

这是最简单的方法,可以在任何地方使用,实际上是退出应用程序,您可以打开很多活动,仍然可以毫无问题地退出所有活动。

在按钮上单击示例

public void exitAppCLICK (View view) {

    finishAffinity();
    System.exit(0);

}

或者,如果您想要一些好东西,例如带有3个按钮的“是”和“取消”的警报对话框

// alertdialog for exit the app
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);

// set the title of the Alert Dialog
alertDialogBuilder.setTitle("your title");

// set dialog message
alertDialogBuilder
        .setMessage("your message")
        .setCancelable(false)
        .setPositiveButton("YES"),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,
                                        int id) {
                        // what to do if YES is tapped
                        finishAffinity();
                        System.exit(0);
                    }
                })

        .setNeutralButton("CANCEL"),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,
                                        int id) {
                        // code to do on CANCEL tapped
                        dialog.cancel();
                    }
                })

        .setNegativeButton("NO"),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,
                                        int id) {
                        // code to do on NO tapped
                        dialog.cancel();
                    }
                });

AlertDialog alertDialog = alertDialogBuilder.create();

alertDialog.show();

3
这是正确的答案,我一直在寻找。谢谢
浮木

如果我在应用中使用了FCM或后台任务,那我不会有问题吗?
roghayeh hosseini

这就是我需要从内存中擦除应用程序的需要
A1m

请不要使用System.exit(0);您不应该释放该内存,系统会在需要时为您处理。这是预期的行为。
crgarridos

30

如果您确实需要终止应用程序,请认真考虑:为什么不让操作系统找出何时何地释放资源?

否则,如果您绝对确定,请使用

finish();

作为对@dave appleton的评论的回应:第一件事读了一个大问题/答案组合@gabriel:退出应用程序是否皱眉?

现在假设我们已经有了,这里的问题仍然有答案,那就是如果您要执行退出操作所需的代码是finish()。显然,您可以进行多个活动等,但这不是重点。让我们按一些用例运行

  1. 您想让用户因为内存使用而退出所有操作,并且“不在后台运行?怀疑”。让用户在后台停止某些活动,但让OS杀死所有不需要的资源。
  2. 您希望用户不进入应用程序的上一个活动吗?好吧,要么对其进行配置以使其不需要,要么您需要一个额外的选项。如果在大多数情况下back = previous-activity起作用,那么用户是否要做其他事情就不按家吗?
  3. 如果需要某种重设,则可以了解是否/如何/等退出了应用程序,并且如果您的活动再次得到关注,则可以对此进行操作,显示一个新的屏幕,而不用重新启动原位置。

因此,最后,当然finish()不会杀死一切,但是我认为它仍然是您需要的工具。如果有一个用例“杀死所有活动”,我还没有找到它。


30
调用finish()不会终止该应用程序。finish()一直使用:Call this when your activity is done and should be closed.与点击“返回”按钮具有相同的效果。
Tanner Perrien 2011年

完成将杀死活动。这与杀死应用程序有何不同?
Nanne 2011年

“完成”或“杀死” Activity(不是Application)没有错。例如,您可以开始一个新活动以向用户显示一些信息。超时或按“确定”后,您可能会打电话finish()返回通话活动。
Tanner Perrien 2011年

42
大多数Android应用程序都有多个活动。
CommonsWare

4
@Nanne-锁定屏幕是您何时要停止所有活动的示例。假设您登录到银行应用程序。在一段时间没有用户交互的情况下,锁定屏幕启动。如果有人从锁定屏幕上点击“后退”按钮,您将要停止所有活动!
Jabari

19

我认为在某些情况下应终止应用程序。例如,有一个应用程序只能在登录后才能使用。登录活动有两个按钮,“登录”和“取消”。当您单击“取消”按钮时,这绝对意味着“终止应用程序”。没有人希望应用程序在后台运行。因此,我同意某些情况下需要关闭该应用程序。


2
我完全同意这个用例。还要考虑我的安全应用程序,该应用程序必须在某个位置可用,并且如果用户不在该位置,则最好关闭它。我该怎么办?
Sydwell 2014年

18

创建一个ExitActivity并在清单中声明。并要求ExitActivity.exit(context)退出应用。

public class ExitActivity extends AppCompatActivity {

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

    public static void exit(Context context) {
        Intent intent = new Intent(context, ExitActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        context.startActivity(intent);
    }

}

这是投票最多的答案,但这是一个hack。在大多数(如果不是全部)设备上,在onCreate上调用finish会出现故障。
DoruChidean '18 -10-25

嗯,这是一个小技巧,但不是小故障。首先要调用exit(),它位于所有活动的顶部,顶部和任务明确,然后完成。在这里,你退出。
vivek '18 -10-29

1
请记住在清单中声明此类。+1是聪明的骇客。
塔斯林·奥塞尼

这工作了!投票
TuanDPH

17

android中没有应用程序退出,SampleActivity.this.finish(); 将完成当前活动。

当您从一项活动切换到另一项活动时,请继续完成上一个活动

Intent homeintent = new Intent(SampleActivity.this,SecondActivity.class);
startActivity(homeintent);
SampleActivity.this.finish();

13

首先,此方法需要最小Api 16。

我将解决方案分为三部分,以更广泛地解决此问题。

1.如果要在活动中退出应用程序,请使用以下代码片段:

if(Build.VERSION.SDK_INT>=16 && Build.VERSION.SDK_INT<21){
    finishAffinity();
} else if(Build.VERSION.SDK_INT>=21){
    finishAndRemoveTask();
}

2.如果要在非Activity类中退出该应用程序,该类可以访问Activity,请使用以下代码片段:

if(Build.VERSION.SDK_INT>=16 && Build.VERSION.SDK_INT<21){
    getActivity().finishAffinity();
} else if(Build.VERSION.SDK_INT>=21){
    getActivity().finishAndRemoveTask();
}

3.如果要退出非Activity类的应用程序并且无法访问Activity(例如Service),则建议您使用BroadcastReceiver。您可以将此方法添加到项目中的所有“活动”中。

创建LocalBroadcastManager和BroadcastReceiver实例变量。如果需要,可以替换getPackageName()+“。closeapp”。

LocalBroadcastManager mLocalBroadcastManager;
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals(getPackageName()+".closeapp")){
            if(Build.VERSION.SDK_INT>=16 && Build.VERSION.SDK_INT<21){
                finishAffinity();
            } else if(Build.VERSION.SDK_INT>=21){
                finishAndRemoveTask();
            }
        }
    }
};

将它们添加到Activity的onCreate()方法中。

mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(getPackageName()+".closeapp");
mLocalBroadcastManager.registerReceiver(mBroadcastReceiver, mIntentFilter);

另外,不要忘记在Activity的onDestroy()方法中调用注销接收器

mLocalBroadcastManager.unregisterReceiver(mBroadcastReceiver);

对于退出应用程序,您必须使用LocalBroadcastManager发送广播,我在扩展Service的PlayService类中使用了该广播。

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(PlayService.this);
localBroadcastManager.sendBroadcast(new Intent(getPackageName() + ".closeapp"));

10

您可以使用finishAndRemoveTask ()API 21

公共无效finishAndRemoveTask()

完成此任务中的所有活动,并将其从最近任务列表中删除。


8

这取决于您要关闭应用程序的速度。

关闭应用程序的安全方法是finishAffinity();。

所有进程完成处理后,它将关闭您的应用程序。这可能需要一些时间。如果您以这种方式关闭您的应用程序,并在短时间后重新启动它,则新应用程序可能以相同的过程运行。具有旧应用程序的所有未完成过程和单例对象。

如果您想确定自己的应用已完全关闭,请使用System.exit(0);。

这将立即关闭您的应用程序。但是有可能损坏应用程序已打开的文件或对共享首选项进行的编辑未完成。因此,请谨慎使用。

如果将看门狗与长时间运行的任务结合使用,则可以看到不同方法的影响。

new ANRWatchDog(2000).setANRListener(new ANRWatchDog.ANRListener() {
    public void onAppNotResponding(ANRError error) {
        MainActivity.this.finishAffinity();
        System.exit(0);
    }
}).start();
for(int i = 0; i < 10; ++i){
    --i;
}

这会在2秒后杀死您的应用程序,而不会显示ANR对话框或类似内容。如果删除System.exit(0),请运行此代码,然后在关闭应用程序后重新启动该应用程序,由于无休止的循环仍在运行,您将遇到一些奇怪的行为。


8

finish()如果您在Activity或,getActivity().finish()则最好使用Fragment

如果要完全退出该应用程序,请使用:

getActivity().finish();
System.exit(0);

6

退出应用程序的简便方法

Intent homeIntent = new Intent(Intent.ACTION_MAIN);
homeIntent.addCategory(Intent.CATEGORY_HOME);
homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);

这只是带回主屏幕还是实际上杀死了该应用程序?
rpattabi '19



5

我们希望代码既健壮又简单。该解决方案适用于旧设备和新设备。

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        getActivity().finishAffinity();
    } else{
        getActivity().finish();
        System.exit( 0 );
    }

5

与@MobileMateo相似,但在Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    this.finishAffinity()
} else{
    this.finish()
    System.exit(0)
}

4

我不确定这是否会皱眉,但这就是我的做法...

第1步-我通常有一个包含要全局访问的方法和变量的类。在此示例中,我将其称为“ App”类。在类内为您的应用具有的每个活动创建一个静态Activity变量。然后创建一个称为“ close”的静态方法,如果finish()这些Activity变量不是null,则将在每个这些Activity变量上运行该方法。如果您有主/父活动,请最后关闭它:

public class App
{
    ////////////////////////////////////////////////////////////////
    // INSTANTIATED ACTIVITY VARIABLES
    ////////////////////////////////////////////////////////////////

        public static Activity activity1;
        public static Activity activity2;
        public static Activity activity3;

    ////////////////////////////////////////////////////////////////
    // CLOSE APP METHOD
    ////////////////////////////////////////////////////////////////

        public static void close()
        {
            if (App.activity3 != null) {App.activity3.finish();}
            if (App.activity2 != null) {App.activity2.finish();}
            if (App.activity1 != null) {App.activity1.finish();}
        }
}

步骤2-在您的每个活动中,覆盖onStart()onDestroy()方法。在中onStart(),将您的App类中的静态变量设置为等于“ this”。在中onDestroy(),将其设置为null。例如,在“ Activity1”类中:

@Override
public void onStart()
{
    // RUN SUPER | REGISTER ACTIVITY AS INSTANTIATED IN APP CLASS

        super.onStart();
        App.activity1 = this;
}

@Override
public void onDestroy()
{
    // RUN SUPER | REGISTER ACTIVITY AS NULL IN APP CLASS

        super.onDestroy();
        App.activity1 = null;
}

第3步-当您要关闭应用程序时,只需App.close()从任何地方调用即可。所有实例化的活动将关闭!由于您只是关闭活动而没有杀死应用程序本身(如您的示例所示),因此Android可以自由地从那里接管并进行必要的清理。

再说一次,我不知道是否会因为任何原因而皱眉。如果是这样,我很乐意阅读有关原因以及如何改进的评论!


有趣的是,我也将对其他经验丰富的Android开发人员对此看法感兴趣。
鲁迪·克肖

4
通过保持对您活动的引用,您实际上正在泄漏内存!请参阅此内容进行深入讨论。
Managarm

@Managarm该帖子背后的前提是,即使进程(在本例中为Activity)已被破坏,静态变量仍将保留。如果正确地进行房屋清洁,那是没有问题的……因此我在活动的onDestroy()方法中取消引用的原因。
贾巴里

@Jabari啊,我错过了onDestroy部分。在这种情况下,虽然这不是最佳做法,但这不应该成为问题。
Managarm 2014年

1
工作没有任何问题。要api>=16使用finishAffinity()其他方法,请使用此方法。
Nobody先生,2016年

4

退出应用程序会感到皱眉吗?。通过此链接。它回答了您的问题。该系统负责终止应用程序。

假设您有两个活动A和B。您从A导航到B。单击“后退”按钮时,活动B从堆栈中弹出并销毁。后堆栈活动A中的上一个活动为焦点。

您应该将其留给系统来决定何时终止该应用程序。

公共无效 finish()

活动完成且应关闭时调用此方法。

假设您有很多活动。您可以使用操作栏。在单击主页图标时,导航到您的应用程序的MainActivity。在MainActivity中,单击“后退”按钮以退出应用程序。


3

要退出您的应用程序,可以使用以下命令:

getActivity().finish();
Process.killProcess(Process.myPid());
System.exit(1);

同样也要停止服务,请调用以下方法:

private void stopServices() {        
    final ActivityManager activityManager = SystemServices.getActivityManager(context);
    final List<ActivityManager.RunningServiceInfo> runningServices = activityManager.getRunningServices(Integer.MAX_VALUE);
    final int pid = Process.myPid();
    for (ActivityManager.RunningServiceInfo serviceInfo : runningServices) {
        if (serviceInfo.pid == pid && !SenderService.class.getName().equals(serviceInfo.service.getClassName())) {
            try {
                final Intent intent = new Intent();
                intent.setComponent(serviceInfo.service);
                context.stopService(intent);
            } catch (SecurityException e) { 
                 // handle exception
            }
        }
    }
}

2

这可能很晚了,而且按照指导原则,您不应该自己处理生命周期过程(因为os会为您这样做)。建议您在所有活动中注册广播接收器,并finish()在其onReceive() &中添加“ ”,只要您想退出,就可以简单地传递一个意图,指示所有活动都必须关闭。在您的onDestroy()方法中“注销”接收者。


1

这不是一个好决定,因为这违反了Android的应用程序处理原则。除非绝对必要,否则Android不会终止任何进程。这有助于使应用启动更快,因为它们始终保留在内存中。因此,您需要一个非常特殊的原因来终止应用程序的进程。


4
退出应用程序需要真正终止该应用程序。因此应该有一种方法可以确保应用退出
后被

1

单击按钮时退出应用程序的正确而准确的解决方案是使用以下代码:

// On Button返回按下事件

public void onBackPressed()
{ 
   moveTaskToBack(true);
   finish();
}

这只是当前的Android组件(例如活动),而不是整个应用程序
Laogeodritt

这将只发送在后台应用
库马尔·加夫

1

如果您使用的是Kotlin,则退出应用程序和替代方法的正确方法System.exit()是内置方法

exitProcess(0)

请参阅文档

数字0作为参数表示有意退出,并且未发生任何错误。


0

这会杀死任何东西;)

int p = android.os.Process.myPid();
android.os.Process.killProcess(p);


0

我发现从活动中退出应用程序,不破坏Android的逻辑,不向现有活动中添加更多代码并传递额外内容的最简单方法是:

public static void quitApplication (Activity currentActivity) {
    Intent intent = new Intent (currentActivity, QuitApplicationActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

    currentActivity.startActivity (intent);
    currentActivity.finish ();
}

QuitApplicationActivity存在:

public class QuitApplicationActivity extends AppCompatActivity {

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

        finish ();
    }
}

0

@Sivi的答案将关闭应用程序。但返回时,如果您有一些子活动,则可能会打开另一个未完成的活动。我添加noHistory:true了活动,因此返回时的应用程序从MainActivity启动。

<activity 
      android:name=".MainActivity"
      android:noHistory="true">
</activity>

0

只需在终止应用程序的残酷方法列表中添加一个即可:

Process.sendSignal(Process.myPid(), Process.SIGNAL_KILL);


Process.killProcess(Process.myPid())做同样的事,但是更短
ivan8m8 '19

-1

您可以退出完整的应用程序。从而

Intent intent = getBaseContext().getPackageManager()
             .getLaunchIntentForPackage(getBaseContext().getPackageName());
intent .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

它将100%工作。祝你好运!


1
看来这不是答案!
Al-Mothafar

-4

只需在后退按键上使用finish()即可onKeypressed()


4
finish()将关闭活动,但肯定不会确定关闭整个应用程序。
2Dee 2015年
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.