继续学习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,但它现在看起来不太好=(

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


当前回答

我希望随着时间的推移情况会有所改变。如果应用程序进程被操作系统正确沙盒化,用户应该能够杀死应用程序或进程。有一种观点认为,应用程序必须编写得完美无缺,否则用户将只使用遵循所有SDK建议的应用程序。我认为这是一个很高的要求。

其他回答

博客文章“何时在Android应用程序中包含退出按钮”(提示:永远不要)解释得比我好得多。我希望每个Android开发者都读过这本书。

摘录:

In my experience what [the users] really want is: An unambiguous way to guarantee that an app will stop consuming resources (battery, CPU cycles, data transfer, etc.). Many users perceive that an exit button implements this requirement and ask for it to be added. Developers, looking to please their users, obligingly add one. Shortly thereafter they both fail. In most cases the exit button simply calls Activity.finish(). This is exactly equivalent to hitting the back button. Exactly. Services keep running and polling keeps happening. Users may think they've killed the app but they haven't, and soon they'll be even more annoyed. Exit behavior is now ambiguous. Should your exit button just close the Activity, or should it also stop all associated Services, Receivers, and Alarms? What should Back do? What happens if they hit Home instead? What happens if your app has a widget? Should the exit button stop that from updating too? The solution is to make the back button behave as you'd expect the exit button to. Better yet, simply stop consuming resources whenever the app isn't visible.

继续阅读完整的文章。

使用以下代码:

Intent i = new Intent();
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_HOME);
ListActivity.this.startActivity(i);
finish();

首先,永远永远不要使用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)仍然在系统中。

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

这最终会涉及到你的问题,但我首先想解决你在写这篇文章时已经给出的各种答案的各种评论中提出的一些问题。我无意改变你的想法——相反,这些是为将来来阅读这篇文章的人准备的。

关键是我不能考虑到 Android来确定我的应用程序 将被终止。那一定是 用户的选择。

数以百万计的人非常喜欢这种环境根据需要关闭应用程序的模型。这些用户根本不会考虑“终止”Android应用程序,就像他们不会考虑“终止”网页或“终止”恒温器一样。

iPhone用户也是如此,按下iPhone按钮并不一定会“感觉”应用程序被终止了,因为许多iPhone应用程序会在用户停止的地方继续运行,即使应用程序真的被关闭了(因为目前iPhone一次只允许一个第三方应用程序)。

正如我上面所说的,有很多 在我的应用程序(数据是 推送到设备,列出任务 它总是应该在那里,等等)。

我不知道“总是应该在那里的任务列表”是什么意思,但“数据被推送到设备”是一个令人愉快的虚构,无论如何都不应该通过活动来完成。使用定时任务(通过AlarmManager)更新您的数据,以获得最大的可靠性。

我们的用户登录了,不能做什么 每次他们接到电话 Android决定关闭这款应用。

有许多iPhone和Android应用程序可以处理这个问题。通常,这是因为它们保留了登录凭据,而不是强迫用户每次手动登录。

例如,我们希望检查更新 退出应用程序时

这在任何操作系统上都是错误的。众所周知,应用程序“退出”的原因是操作系统正在关闭,然后更新过程将在中间失败。一般来说,这不是一件好事。要么在启动时检查更新,要么完全异步地检查更新(例如,通过计划任务),永远不要在退出时检查更新。

一些评论建议打 返回按钮不杀死应用程序在 所有(见上面我的问题中的链接)。

按后退按钮不会“杀死应用程序”。当用户按下BACK按钮时,它完成了屏幕上的活动。

仅当 用户想要终止它——从来没有 任何其他方式。如果你不会写字 在Android中运行的应用程序, 那么我认为Android不能使用 对于编写真正的应用程序=(

Web应用程序也不能。或者是WebOS,如果我对他们的模式理解正确的话(还没有机会使用)。在所有这些情况下,用户不会“终止”任何事情——他们只是离开。iPhone则有所不同,因为它目前一次只允许运行一件事(除了少数例外),所以离开意味着立即终止应用程序。

有没有办法让我真的戒掉 应用程序?

正如其他人告诉您的那样,用户(通过BACK)或代码(通过finish())可以关闭当前正在运行的活动。对于正确编写的应用程序,用户通常不需要任何其他东西,就像使用Web应用程序不需要“退出”选项一样。


根据定义,没有两个应用程序环境是相同的。这意味着您可以看到环境中的趋势,因为新的出现和其他的被掩盖。

例如,有一种越来越多的运动试图消除“文件”的概念。大多数Web应用程序不会强迫用户考虑文件。iPhone应用程序通常不会强迫用户考虑文件。Android应用程序通常不会强迫用户考虑文件。等等。

类似地,有越来越多的人试图消除“终止”应用程序的概念。大多数Web应用程序不会强制用户注销,而是在一段时间不活动后隐式地将用户注销。Android和iPhone(可能还有WebOS)也是如此。

这需要更多地强调应用程序设计,关注业务目标,而不是坚持与以前的应用程序环境捆绑在一起的实现模型。缺乏时间或意愿这样做的开发人员会对打破现有思维模式的新环境感到沮丧。这不是任何一种环境的错,就像它不是一座山的错,因为风暴围绕着它而不是穿过它。

例如,一些开发环境,如Hypercard和Smalltalk,将应用程序和开发工具混合在一个设置中。除了应用程序的语言扩展(例如,Excel中的VBA, AutoCAD中的Lisp),这个概念并没有流行起来。因此,那些提出了假设应用程序本身存在开发工具的心智模型的开发人员,要么必须改变他们的模型,要么将自己限制在模型成立的环境中。

所以,当你写:

连同其他乱七八糟的东西,我 我认为这正在发展 我们的Android应用就不会 发生。

这似乎是对你最好的选择,就目前而言。同样,我建议你不要尝试将你的应用程序移植到Web上,因为你在Android上报告的一些同样的问题也会在Web应用程序中发现(例如,没有“终止”)。或者,反过来说,如果有一天你把应用移植到Web上,你可能会发现Web应用的流程可能更适合Android,那时你可以重新考虑Android移植。

目前,我在我的应用程序中实现了以下内容。可能这些有助于从应用程序中移动出来,无论你想要的是什么。我从操作栏菜单中调用这个函数。

public static void exitApplication(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        exitApplicationHC(context);
    }
    else {
        exitApplicationPreHC(context);
    }
}

private static void exitApplicationPreHC(Context context) {
    Intent i = new Intent(context, LoginActivity.class);
    i.putExtra(EXTRA_EXIT, true);
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(i);
    if (context instanceof Activity) {
        ((Activity) context).finish();
    }
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static void exitApplicationHC(Context context) {
    Intent i = new Intent(context, LoginActivity.class);
    i.putExtra(EXTRA_EXIT, true);
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
    context.startActivity(i);
}