继续学习Android,我读了以下内容:

Question: Does the user have a choice to kill the application unless we put a menu option in to kill it? If no such option exists, how does the user terminate the application? Answer: (Romain Guy): The user doesn't, the system handles this automatically. That's what the activity lifecycle (especially onPause/onStop/onDestroy) is for. No matter what you do, do not put a "quit" or "exit" application button. It is useless with Android's application model. This is also contrary to how core applications work.

呵呵,我在Android世界里每走一步都会遇到一些问题=(

显然,你不能在Android中退出应用程序(但Android系统可以随时完全销毁你的应用程序)。这是怎么回事?我开始认为这是不可能写一个应用程序的功能作为“正常的应用程序”-用户可以退出应用程序时,他/她决定这么做。这不应该依靠操作系统来完成。

我正在尝试创建的应用程序不是Android市场的应用程序。它不是一个被大众“广泛使用”的应用程序,它是一个将在非常狭窄的商业领域使用的商业应用程序。

我其实很期待为Android平台开发,因为它解决了Windows Mobile和。net中存在的许多问题。然而,上周对我来说有点令人失望……我希望我不必放弃Android,但它现在看起来不太好=(

有办法让我真的退出应用程序吗?


当前回答

这是一个有这么多专家参与的有趣而有见地的讨论。我觉得这篇文章应该从Android开发的主要网站中循环回来,因为它确实围绕着Android操作系统的核心设计之一。

我还想在这里发表我的意见。

到目前为止,我对Android处理生命周期事件的方式印象深刻,它将类似web的体验概念引入原生应用。

话虽如此,我仍然认为应该有一个退出按钮。为什么?... 不是为了我,不是为了泰德,也不是为了在座的任何一位技术大师,而是为了满足终端用户的需求。

虽然我不是Windows的忠实粉丝,但很久以前他们引入了一个大多数终端用户都习惯的概念(X按钮)……“我想在‘我’想要的时候停止运行一个小部件”。

这并不意味着有人(操作系统、开发人员?)会根据自己的判断来处理……它仅仅意味着“我习惯的红色X按钮在哪里”。我的行为应该类似于“按下按钮结束通话”,“按下按钮关闭设备”,等等……这是一种感知。它本身带来了一种满足感,我的行动确实达到了目的。

尽管开发人员可以使用这里给出的建议来欺骗这种行为,但仍然存在这样的看法,即应用程序应该完全停止运行(现在),由最终用户要求的独立、可信和中立的来源(OS)。

其他回答

这很简单。只要遵循我要告诉你的这些指示:

比如你有多个活动,从一个活动到另一个活动。你可能会像这样使用intent:

Intent i1 = new Intent(this, AnotherActivity);
startActivity(i1) 

你只需要添加finish();例如,从头到尾在每个活动上启动intent活动后,

Intent i1=new Intent(this, AnotherActivity);
startActivity(i1) 
finish();

所以当你点击退出按钮时使用的是finish()或System.exit(0)必须完全关闭你的应用程序。

我认为关键是没有必要退出应用程序,除非你的软件有问题。Android会在用户不使用该应用且设备需要更多内存时退出该应用。如果你有一个需要在后台运行服务的应用程序,你可能需要一种方法来关闭服务。

For example, Google Listen continues to play podcast when the app is not visible. But there is always the pause button to turn the podcast off when the user is done with it. If I remember correctly, Listen, even puts a shortcut in the notification bar so you can always get to the pause button quickly. Another example is an app like a twitter app for instance which constantly polls a service on the internet. These types of apps should really allow the user to choose how often to poll the server, or whether even to poll in a background thread.

如果你需要在退出时运行的代码,你可以根据需要重写onPause(), onStop()或onDestroy()。 http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

我只是想在这里为这篇文章的未来读者补充一个更正。这个细微的差别我已经不理解很长一段时间了,所以我想确保你们没有人会犯同样的错误:

如果栈上有多个activity, System.exit()不会杀死你的应用。实际发生的情况是进程被杀死,并立即重新启动,堆栈上少了一个活动。当你的应用程序被强制关闭对话框杀死时,甚至当你试图从DDMS中杀死进程时,也会发生这种情况。据我所知,这是一个完全没有记录的事实。

The short answer is, if you want to exit your application, you've got to keep track of all activities in your stack and finish() ALL of them when the user wants to exit (and no, there is no way to iterate through the Activity stack, so you have to manage all of this yourself). Even this does not actually kill the process or any dangling references you may have. It simply finishes the activities. Also, I'm not sure whether Process.killProcess(Process.myPid()) works any better; I haven't tested it.

另一方面,如果你可以将活动保留在堆栈中,还有另一个方法可以让事情变得超级简单:Activity.moveTaskToBack(true)将简单地将你的进程作为背景并显示主屏幕。

长的答案包括对这种行为背后的哲学的解释。这一理论是基于以下几个假设:

First of all, this only happens when your app is in the foreground. If it is in the background the process will terminate just fine. However, if it is in the foreground, the OS assumes that the user wants to keep doing whatever he/she was doing. (If you are trying to kill the process from DDMS, you should hit the home button first, and then kill it) It also assumes that each activity is independent of all the other activities. This is often true, for example in the case that your app launches the Browser Activity, which is entirely separate and was not written by you. The Browser Activity may or may not be created on the same Task, depending on its manifest attributes. It assumes that each of your activities is completely self-reliant and can be killed/restored in a moment's notice. (I rather dislike this particular assumption, since my app has many activities which rely on a large amount of cached data, too large to be efficiently serialized during onSaveInstanceState, but whaddya gonna do?) For most well-written Android apps this should be true, since you never know when your app is going to be killed off in the background. The final factor is not so much an assumption, but rather a limitation of the OS: killing the app explicitly is the same as the app crashing, and also the same as Android killing the app to reclaim memory. This culminates in our coup de grace: since Android can't tell if the app exited or crashed or was killed in the background, it assumes the user wants to return where they left off, and so the ActivityManager restarts the process.

仔细想想,这是适合这个平台的。首先,这正是当进程在后台被杀死,用户返回到它时所发生的情况,因此它需要在它停止的地方重新启动。其次,这是当应用程序崩溃并呈现可怕的强制关闭对话框时所发生的情况。

Say I want my users to be able to take a picture and upload it. I launch the Camera Activity from my activity, and ask it to return an image. The Camera is pushed onto the top of my current Task (rather than being created in its own Task). If the Camera has an error and it crashes, should that result in the whole app crashing? From the standpoint of the user, only the Camera failed, and they should be returned to their previous activity. So it just restarts the process with all the same Activities in the stack, minus the Camera. Since your Activities should be designed so that they can be killed and restored at the drop of a hat, this shouldn't be a problem. Unfortunately, not all apps can be designed that way, so it is a problem for many of us, no matter what Romain Guy or anyone else tells you. So, we need to use workarounds.

所以,我最后的建议是:

Don't try to kill the process. Either call finish() on all activities or call moveTaskToBack(true). If your process crashes or gets killed, and if, like me, you need the data that was in memory which is now lost, you'll need to return to the root activity. To do this, you should call startActivity() with an Intent that contains the Intent.FLAG_ACTIVITY_CLEAR_TOP flag. If you want to kill your app from the Eclipse DDMS perspective, it had better not be in the foreground, or it will restart itself. You should press the Home button first, and then kill the process.

如果没有退出函数,应用程序开发人员就可以杀死自己的应用程序,这是非常糟糕的设计。

我的应用程序需要允许用户在运行时动态地更改数据,用户需要重新启动我的应用程序才能使更改生效,但Android不允许我的应用程序自行重新启动。Android操作系统有一个非常糟糕的设计应用程序生命周期。

首先,永远永远不要使用System.exit(0)。这就像一拳打在一个人的头上让他睡着一样!

第二,我正面临这个问题。在分享我的解决方案之前,我想分享一下我的想法。

我认为“退出按钮”很愚蠢。真的真的真的很傻。我认为用户(消费者)要求你的应用程序有一个退出按钮也是愚蠢的。他们不了解操作系统是如何工作的,以及如何管理资源(它做得很好)。

我认为如果你写了一段好的代码,在正确的时间和条件下做正确的事情(更新、保存和推送),并使用正确的东西(服务和接收器),它会工作得很好,没有人会抱怨。

但要做到这一点,你必须研究并了解Android上的工作原理。 总之,这是我为用户提供“退出按钮”的解决方案。

我创建了一个选项菜单,在每个活动中总是可见的(我有一个超级活动,这样做)。

当用户点击这个按钮时,会发生这样的情况:

Intent intent = new Intent(this, DashBoardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

SharedPreferences settings = getSharedPreferences(getString(PREF_ID), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(FORCE_EXIT_APPLICATION, true);

  // Commit the edits!
editor.commit();
startActivity(intent);
finish();

我在SharedPreferences中保存我想要终止应用的那个,我启动了一个Intent。请看那些旗子;这些将清除我所有的backstack,调用我的DashBoard Activity,这是我的“home”Activity。

所以在我的仪表板活动中,我在onResume中运行这个方法:

private void checkIfForceKill() {

    // CHECK IF I NEED TO KILL THE APP

    // Restore preferences
    SharedPreferences settings = getSharedPreferences(
            getString(MXMSettingHolder.PREF_ID), Context.MODE_PRIVATE);
    boolean forceKill = settings.getBoolean(
            MusicSinglePaneActivity.FORCE_EXIT_APPLICATION, false);

    if (forceKill) {

        //CLEAR THE FORCE_EXIT SETTINGS
        SharedPreferences.Editor editor = settings.edit();
        editor.putBoolean(FORCE_EXIT_APPLICATION, false);

        // Commit the edits!
        editor.commit();

        //HERE STOP ALL YOUR SERVICES
        finish();
    }
}

它会运行得很好。

唯一一件我不明白为什么会发生的事情是,当我做最后的完成(我已经检查过:它遵循所有正确的onPause→onStop→onDestroy流程)应用程序仍然在最近的活动(但它是空白的)。

似乎最新的意图(已经启动了DashboardActivity)仍然在系统中。

我还得挖更多才能把它挖出来。