Android,完成所有活动

Posted

技术标签:

【中文标题】Android,完成所有活动【英文标题】:Android, Finish all activities 【发布时间】:2011-06-13 02:36:04 【问题描述】:

单击退出按钮时,我需要完成 android 应用程序中运行的所有活动。我该怎么做?

我想要什么:

    屏幕上带有退出选项的选项菜单。 当我点击退出菜单时,应用程序应该关闭。

【问题讨论】:

【参考方案1】:

如何制作一个让用户立即完成所有活动的按钮

当用户希望退出所有打开的活动时,让他们按下一个按钮,该按钮会加载在您的应用启动时运行的第一个活动(传递一个意图以清除所有其他活动)。然后在剩下的一个活动(LoginActivity)中,在 onCreate 中放置一些代码,让它选择自毁。

详情:

创建一个按钮并将其命名为“exit”,为该按钮创建一个按钮监听器,并将以下代码放入其中。它所做的是加载活动,通过清除它下面的所有活动使其成为唯一剩余的活动。

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

以上代码清空了LoginActivity下的所有Activity。 LoginActivity 必须是您的应用程序运行的第一个活动。所以现在我们只剩下激活了 LoginActivity。现在我们必须让 LoginActivity 来检查putExtra 参数,如果它的值为“EXIT”,那么也销毁它自己。

在LoginActivity的onCreate和onResume中加入如下代码,检查“EXIT”参数,看到就结束:

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

为什么这么难,为什么不只有一个 exitAllActivites() 函数?

Android 操作系统开发人员让这变得困难,因为他们不希望您给用户一个退出按钮。他们希望用户永远不会关心他们的应用程序是否正在运行。如果他们想要它,他们就会运行它,如果他们不想要它,他们就会停止使用它。这种模式有很多好处,因为可以销毁应用程序以腾出空间来接听电话和大量使用地图,然后他们重新运行您的应用程序,从中断的地方继续,而不必重新启动从头开始。

因此,如果您使用此代码,请尝试与 Android 开发者对 Android 的愿景合作,并使其能够在任何时候销毁/重新创建应用程序,并且用户始终可以从上次中断的地方继续。要求用户“退出”很麻烦。

【讨论】:

“它所做的是加载活动,使其成为唯一剩余的活动,并清除所有其他活动。” 不完全准确。根据文档,假设你的用户从活动 A 到 B 到 C 到 D,然后从 D 你通过 Intent.FLAG_ACTIVITY_CLEAR_TOP 显示活动(b),然后 B 之后的所有活动都将完成,即 C 和 D。A 仍将是在记忆中。 如果 LoginActivity 已经在栈上,那么这段代码将调用它的 onResume() 方法而不是 onCreate()。 @ajacian81 仍然不正确。使用您的示例,如果您使用 FLAG_ACTIVITY_CLEAR_TOP 启动活动 B,Android 将在 B 之上完成所有活动,它还将完成 B 的当前实例并创建 B 的新实例(除非活动 B 已声明 launchMode="singleTop" in the manifest, in which case it will just call onNewIntent () 在 B) 的现有实例上。 @IgorGanapolsky 这不正确。如果LoginActivity 已经在堆栈中,则此代码将在LoginActivity 的该实例上调用finish() 并创建LoginActivity 的新实例并照常调用onCreate()((除非LoginActivity 已声明@987654332 @ 在清单中,在这种情况下,它只会在 LoginActivity 的现有实例上调用 onNewIntent()。【参考方案2】:

使用StartActivityForResult 函数启动一个新的Activity,当用户按下EXIT 按钮时,发送一个唯一值作为resultcode。在onActivityForResult func 中检查此resultcode,如果找到相同的唯一代码,则完成活动。

【讨论】:

【参考方案3】:

我不明白那些说不应该这样做的人。使用内置方法可以很容易地关闭活动。

官方文档中没有任何地方说不应该这样做。

对于那些认为不应该出于任何目的这样做的人,也许你想不出这样做的理由。这样做有很多正当理由。而且由于它是 Android 代码中内置的一种方法。Google 还决定您可能需要根据您的使用情况。并非所有人都只为 Android 创建消费者应用程序。

所以要完成这项任务..关闭堆栈中的所有活动

public void quitApp()
      this.finishAffinity();

我创建了一个作为默认启动器运行的自助服务终端应用。所以我需要一种方法来退出应用程序以访问设备上的设置或其他应用程序。因此,在管理员活动中,我放置了一个密码键盘。在用户输入正确的密码后,应用程序需要退出到原始启动器。我使用了上面的代码。

【讨论】:

谢谢!这是一个很大的帮助。谷歌的第一次设置向导有一个强制退出,所以我不相信他们没有为我的应用程序支持显式完成()的整个体验。我当然需要它。【参考方案4】:

您不应在 Android 应用程序中实现退出按钮。

阅读http://groups.google.com/group/android-developers/browse_thread/thread/1bf0f7a4a9c62edd/a0a4aedf21ae5f76?pli=1

干杯

【讨论】:

我真的不喜欢这样的“答案”。是的,一般应用程序不应被显式关闭。但这并不意味着没有任何情况下它可以派上用场,而且提出问题并找到它而不是正确的解决方案是非常烦人的。当然,在真正的答案中包含一个通常不应该这样做的免责声明并不是一个坏主意,但单独的免责声明并不是一个答案。 是的,我同意你的观点。但是,我遇到过很多情况,项目所有者要求的功能根本没有任何意义,我认为在某些情况下,重要的是要突出指出这一点,而不是发布解决方案以及可能赢得的小免责声明不被阅读。 欢迎您在没有回答问题的所有内容所属的 cmets 中执行此操作。此外,如果您不回答问题,其他人会回答,而您的“答案”被接受并不总是幸运的。如果您担心免责声明未被阅读,请将其放大like this。我什至看到an answer 对为什么不应该这样做的解释远远大于解决方案本身。【参考方案5】:

如何关闭Android中的所有Activity:

为什么 Android 操作系统开发人员告诉我不要创建退出按钮?

如果你给开发者一把锤子,他们就会使用它,一切都变成钉子,所以不要给他们锤子。这就是为什么没有单线可以退出所有活动的原因。

为什么退出按钮如此糟糕?

您可能会感到沮丧,想知道为什么在 Android 中杀死所有活动如此困难。这很难做到,因为您必须咬紧牙关,了解您是如何创建堆栈的,以及它的外观。应该以什么顺序销毁活动?如果用户接到电话并需要尽快核对您的应用程序怎么办?你需要有一个放松的计划。它不能依赖活动管理器来照看您的应用程序。如果你想杀死你的应用程序,操作系统开发人员会扭曲你的手臂来制定一个展开计划,因为他们不希望你的应用程序在 Activity Manager 启动时出现任何错误。

我继续描述的这种自毁机制与 Activity Manager 配合使用,会产生级联效应,导致所有 Activity 自行完成,无论它们如何组织。

要将这种级联自毁添加到您的应用中,请执行以下三项操作:

如果您是 android 新手并且以前从未这样做过,我建议您创建一个全新的裸机 android 项目来测试它并了解它的行为方式。只有当你“啊哈”地理解为什么会这样时,你才能提取下面代码的有用性来取悦用户。

    将此覆盖方法放在您的每个活动中:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    
        //onActivityResult is called when a launched activity exits, giving 
        //you the requestCode, 1234, that you started it with. The resultCode 
        //it returned, 900, and any additional Intent data from it. The 
        //resultCode will be RESULT_CANCELED if the activity explicitly 
        //returned that, didn't return any result, or crashed during its 
        //operation.
    
        switch(resultCode)
        
            case 900:         //Make 900 a final global variable if you want.
                              //900 means CLOSE_ALL_ACTIVITIES to me.  It is 
                              //a signal that the self destruct button has 
                              //been initiated and all activities should end.
    
              setResult(900); //setResult sets the resultCode that will be passed
                              //to onActivityResult in the activity that called
                              //this activity.  this will immediately tell the 
                              //parent to self destruct even before the next 
                              //command, finish(), is run.
    
              finish();     //Now stop this activity.
              break;
        
        super.onActivityResult(requestCode, resultCode, data);
    
    

    如果您有 3 个以上的活动,请考虑让每个活动都扩展一个“MyAppActivity”,并在其中包含上述代码。如果您发现自己将上述方法复制/粘贴到 15 个不同的活动中,那么就给自己一记耳光,然后上一堂好的面向对象编程的课程。 Then read this.

    (Details about onActivityResult.),(Details about setResult.)

    当你让用户开始一个新的活动时,你必须这样做:

    Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
    startActivityForResult(myIntent, 1234);
    
    //The 2nd parameter of startActivityForResult is what is sent to 
    //resultCode in the onActivityResult method.  The code `1234` 
        //doesn't do anything here because it is a flag that is 
        //ignored in onActivityResult.  
    

    More information about startActivityForResult.

    如果你不使用startActivityForResult,那么自毁解开将不起作用。

    当你想退出你的应用程序时,像这样启动自毁:

    setResult(900);    //900 is the self destruct code.
    finish();
    

然后活动堆栈展开计划级联通过整个应用程序。

【讨论】:

【参考方案6】:

您应该对自己进行此操作。阅读这篇好博文:http://blog.radioactiveyak.com/2010/05/when-to-include-exit-button-in-android.html

【讨论】:

【参考方案7】:

完成所有活动的另一种解决方案对我有用:

在我的Controller 类的某处,有一种方法可以启动关机:

/**
 * Ask for application shutdown.
 * 
 * <p>
 * After the call, the system shall wipe the entire task and activities and
 * then call @link #onTaskWiped() to finish the cleaning.
 * </p>
 */
public void attemptShutdown() 
    // wipe the task and its activities.
    Application app = getApplication();
    Intent intent = new Intent(app, ShutdownActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    app.startActivity(intent);

ShutdownActivity 只是在完成之前执行数据清理,就像之前所说的那样。

/**
 * This activity is started by @link Controller#attemptShutdown() to wipe the
 * entire task and activities. It calls @link Controller#onTaskWiped() in
 * @link #onCreate(Bundle) and finish immediately after.
 */
public class ShutdownActivity extends Activity 
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        // this is where you release the application data.
        Controller.controller.onTaskWiped();

        finish();
    

最后是清单部分。我设置了透明样式,避免出现activity时出现小闪,但似乎效果不佳。

<activity android:label="Exiting..."
android:name=".ShutdownActivity"
android:excludeFromRecents="true"
android:theme="@style/Theme.Transparent" />

【讨论】:

以上是关于Android,完成所有活动的主要内容,如果未能解决你的问题,请参考以下文章

Android - Asynctask完成时的下一个活动

Android:如何在所有后台线程完成后启用按钮

android学习-1

Android 无法完成活动

Android:Html 5 视频在活动完成时不会停止

android - 从活动调用完成会破坏托管片段吗?