关于安卓:退出一个不受欢迎的应用程序吗?

Is quitting an application frowned upon?

继续学习安卓系统,我只需阅读以下内容:

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中存在的许多问题。然而,上周对我来说有点令人失望…我希望我不必放弃安卓,但现在看起来不太好=(

我有没有办法真的退出申请?


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

The point is that I cannot allow for
Android to determine when my app is
going to be terminated. that must be
the choice of the user.

Ok.

数以百万计的人对环境根据需要关闭应用程序的模型非常满意。这些用户根本不想"终止"Android应用程序,而只是想"终止"网页或"终止"恒温器。好的。

iPhone用户的方式也大致相同,因为按下iPhone按钮不一定会"感觉"应用程序被终止,因为许多iPhone应用程序会在用户停止使用的地方启动,即使应用程序确实被关闭(因为目前iPhone只允许一次使用一个第三方应用程序)。好的。

As I said above, there is a lot of
things going on in my app (data being
PUSHed to the device, lists with tasks
that always should be there, etc.).

Ok.

我不知道"列出总应该存在的任务"是什么意思,但是"数据被推到设备上"是一个令人愉快的虚构,在任何情况下都不应该由一个活动来完成。使用计划任务(通过AlarmManager更新数据以获得最大的可靠性。好的。

Our users log in and can't be doing
that every time they get a phone call
and Android decides to kill the app.

Ok.

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

For example, we want to check updates
when exiting the application

Ok.

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

Some comments suggest that hitting the
back button does not kill the app at
all (see link in my question above).

Ok.

按下后退按钮不会"终止应用程序"。当用户按下后退按钮时,它完成屏幕上的活动。好的。

It should only terminate when the
users wants to terminate it - never
ever any other way. If you can't write
apps that behave like that in Android,
then I think that Android can't be used
for writing real apps =(

Ok.

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

Is there a way for me to really quit
the application?

Ok.

正如其他人告诉您的,用户(通过back)或您的代码(通过finish())可以关闭当前正在运行的活动。对于正确编写的应用程序,用户通常不需要任何其他东西,而只需要一个"退出"选项即可使用Web应用程序。好的。

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

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

同样,有越来越多的运动试图消除"终止"应用程序的概念。大多数Web应用程序并不强制用户注销,而是在一段时间不活动后隐式地注销用户。在Android上也是一样,在较小程度上,iPhone(可能还有WebOS)。好的。

这需要更多地强调应用程序设计,关注业务目标,而不是坚持与以前的应用程序环境相联系的实现模型。缺乏时间或倾向于这样做的开发人员会对新环境感到沮丧,因为新环境破坏了他们现有的心理模型。这不是任何一个环境的错,更不是山间的错,因为周围有风暴,而不是穿过山间。好的。

例如,一些开发环境(如hypercard和smalltalk)将应用程序和开发工具混合在一个设置中。除了应用程序的语言扩展(例如,Excel中的VBA、AutoCAD中的Lisp),这个概念没有太多的应用。因此,开发人员必须改变他们的模型,或者将自己限制在他们的模型可以实现的环境中,他们提出了假定应用程序本身存在开发工具的心理模型。好的。

所以,当你写:好的。

Along with other messy things I
discovered, I think that developing
our app for Android is not going to
happen.

Ok.

对你来说,现在看来这是最好的。同样,我建议您不要尝试将应用程序移植到Web,因为您在Android上报告的一些问题也会在Web应用程序中发现(例如,没有"终止")。或者,相反地,有一天如果你把你的应用移植到网络上,你会发现网络应用的流程可能更适合Android,那时你可以重新访问一个Android端口。好的。好啊。


我只想在这里为这篇文章的未来读者添加一个修正。这种特殊的细微差别在我很长一段时间内都无法理解,所以我想确保你们中没有人会犯同样的错误:好的。

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

简短的回答是,如果您想退出应用程序,您必须跟踪您的堆栈中的所有活动,并且当用户想要退出时,必须跟踪finish()所有这些活动(不,没有迭代活动堆栈的方法,因此您必须自己管理所有这些活动)。即使这样也不会真正杀死进程或您可能拥有的任何悬空引用。它只是简单地完成活动。另外,我不确定Process.killProcess(Process.myPid())是否工作得更好,我还没有测试过。好的。

另一方面,如果您可以将活动保留在堆栈中,那么还有另一种方法可以让事情变得非常简单:Activity.moveTaskToBack(true)将简单地对您的流程进行背景处理并显示主屏幕。好的。

答案很长,包括解释这种行为背后的哲学。这种哲学是由许多假设产生的:好的。

  • 首先,只有当你的应用程序在前台时才会发生这种情况。如果它在后台,进程将终止。但是,如果它在前台,操作系统假定用户想继续做他/她正在做的事情。(如果您试图从DDMS中终止进程,应该先点击Home按钮,然后终止它)
  • 它还假定每个活动独立于所有其他活动。这通常是正确的,例如,在您的应用程序启动浏览器活动的情况下,这是完全独立的,不是由您编写的。浏览器活动可以在同一任务上创建,也可以不在同一任务上创建,这取决于其清单属性。
  • 它假定你的每一个活动都是完全自力更生的,并且可以在一瞬间被杀死/恢复。(我很不喜欢这种特殊的假设,因为我的应用程序有许多依赖大量缓存数据的活动,这些数据太大,在onSaveInstanceState期间无法有效序列化,但您会怎么做?)对于大多数写得很好的Android应用程序来说,这应该是真的,因为你永远不知道你的应用程序什么时候会在后台被淘汰。
  • 最后一个因素不是假设,而是操作系统的局限性:明确地终止应用程序与应用程序崩溃是相同的,也与Android终止应用程序以回收内存相同。这在我们的Coup de Grace中达到了顶点:由于Android无法判断应用程序是否退出、崩溃或在后台被杀,因此它假定用户希望返回停止的位置,因此ActivityManager重新启动了该过程。
  • 当您考虑它时,这对于平台是合适的。首先,当进程在后台被终止并且用户返回时,这正是发生的事情,因此需要在停止的地方重新启动它。第二,当应用程序崩溃并出现可怕的强制关闭对话框时,会发生这种情况。好的。

    比如说,我希望我的用户能够拍摄照片并上传。我从我的活动中启动相机活动,并要求它返回图像。相机被推到当前任务的顶部(而不是在自己的任务中创建)。如果摄像头出现错误并崩溃,是否会导致整个应用程序崩溃?从用户的角度来看,只有相机出现故障,它们应该返回到以前的活动。所以它只是用堆栈中所有相同的活动重新启动这个过程,不包括摄像机。因为你的活动应该被设计成可以在掉帽子的时候被杀死和恢复,这不应该是一个问题。不幸的是,并不是所有的应用程序都可以这样设计,所以这对我们中的许多人来说都是一个问题,不管罗姆人或其他人告诉你什么。所以,我们需要使用解决方法。好的。

    所以,我的结束建议是:好的。

    • 不要试图扼杀这个过程。在所有活动中都可以调用finish()或调用moveTaskToBack(true)
    • 如果您的进程崩溃或被杀死,并且像我一样,您需要内存中的数据,而这些数据现在丢失了,那么您需要返回到根活动。为此,您应该调用startActivity()以包含Intent.FLAG_ACTIVITY_CLEAR_TOP标志。
    • 如果你想从EclipseDDMS的角度杀死你的应用程序,最好不要放在前台,否则它会自动重启。您应该先按下Home按钮,然后终止该过程。

    好啊。


    我所有的应用程序都有退出按钮…因此我经常得到用户的积极评价。我不在乎平台的设计是否符合应用程序不需要的方式。说"别把它们放在那儿"有点可笑。如果用户想退出…我给他们提供了这样做的机会。我认为这根本不能降低安卓的运行方式,而且似乎是一个很好的实践。我了解生命周期…我的观察是Android在处理它方面做得不好……这是一个基本事实。


    不要把你的应用看作一个整体应用。它是一组用户可以与您的"应用程序"和通过Android服务提供的"功能"进行交互的用户界面。

    不知道你的神秘应用"做什么"并不重要。让我们假设它进入一些超级安全的企业内部网,执行一些监视或交互,并保持登录状态,直到用户"退出应用程序"。因为您的IT部门命令它,用户必须非常清楚他们何时进入或离开内部网。因此,您认为用户"退出"很重要的心态。

    这很简单。创建一个服务,将一个正在进行的通知放在通知栏中,说"我在内部网中,或者我正在运行"。让该服务执行应用程序所需的所有功能。具有绑定到该服务的活动,以允许用户访问与您的"应用程序"交互所需的UI位。并有一个android菜单->退出(或注销,或其他)按钮,告诉服务退出,然后关闭活动本身。

    这正是你所说的你想要的。以Android方式完成。看看google talk或google maps导航中关于这种"退出"的可能心态的例子。唯一的区别是,在用户希望恢复应用程序时,从活动中按back按钮可能会使Unix进程处于等待状态。这与现代的操作系统没有什么不同,后者将最近访问的文件缓存在内存中。退出Windows程序后,它所需的最有可能的资源仍在内存中,等待在加载时被其他资源替换,因为它们不再需要了。Android也是一样。

    我真的不明白你的问题。


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

    我还想在这里加上我的两分钱。

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

    虽然我说过我仍然相信应该有一个Quit按钮。为什么?…不是为了我、泰德或这里的任何技术大师,而是为了满足最终用户的需求。

    虽然我不太喜欢Windows,但很久以前,他们引入了一个大多数终端用户习惯的概念(一个x按钮)。我想在"我"想要的时候停止运行小部件。

    这并不意味着有人(操作系统、开发人员?)由他/她自己决定…它的意思是"我的红色X按钮在哪里,我习惯了"。我的操作应该类似于"按下按钮时结束呼叫"、"按下按钮关闭设备"等等…这是一种感觉。从本质上来说,我的行动确实达到了它的目的,这使我感到满意。

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


    您可以按back按钮或在您的Activity中调用finish()退出。如果你想明确地杀死它,只需从一个MenuItem中调用finish()

    Romain并不是说它不能完成,而是说它是毫无意义的,用户不需要关心放弃或保存他们的工作或其他事情,因为应用程序生命周期的工作方式鼓励您编写智能软件,无论发生什么,它都能自动保存和恢复其状态。


    这场争论归结为一个古老的问题,即开发人员是最了解还是用户最了解。人类因素的各个领域的专业设计师每天都在为此而奋斗。

    泰德指出,市场上下载最多的应用程序之一就是"应用杀手"。当人们退出应用程序时,会得到一点额外的血清素。他们习惯用台式机/笔记本电脑。它能让事情快速发展。它使处理器保持冷却,风扇不打开。它耗电更少。

    当你认为一个移动设备是一艘小得多的船,那么你可以特别欣赏他们"扔下你不再需要的东西"的动机。现在,Android的开发者们认为,操作系统是最了解的,退出应用程序是很古老的。我全心全意支持这一点。

    然而,我也相信你不应该让用户失望,即使这种挫折是由他们自己的无知造成的。正因为如此,我得出结论,拥有一个"退出"选项是一个很好的设计,即使它主要是一个安慰剂按钮,只不过是关闭一个视图。


    泰德,你正在努力完成的事情是可以完成的,也许你现在并不是怎么想的。

    我建议你仔细阅读活动和服务。停止使用术语"app",并开始引用组件,即活动、服务。我认为你只需要了解更多关于Android平台的信息;这是一个标准PC应用程序的思维方式的改变。事实上,你的文章中没有"活动"一词(缺少常见问题的引述,即没有你的话),这告诉我你需要多读一些。


    博客帖子何时在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.

    继续阅读完整的文章。


    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.

    1:完全退出一个应用程序通常是不具数据性的,但它并不是无用的。如果Windows没有退出选项怎么办?由于内存已满,操作系统不得不猜测您使用的是哪种程序,因此系统会非常缓慢。我不在乎罗曼·盖伊,甚至拉里·佩奇和谢尔盖·布林说了什么——这些都是毋庸置疑的事实:在启动新的应用程序之前,当系统必须杀死任务才能获得内存时,运行速度会变慢。你不能告诉我不需要时间就可以杀死一个应用程序!即使是来自遥远恒星的光也需要时间…允许用户完全关闭应用程序有一些用途。

    2:与核心应用程序的工作方式相反?那是什么意思?当我现在运行完一个应用程序后,它就不再做任何工作了……当需要内存时,它只是等待被操作系统杀死。

    总之,在最小化和退出之间有明显的区别,而对于另一个来说,这两个点都不适合。我们是不是在每个螺丝里都放一把螺丝刀?或者每扇门都有一把钥匙?我们是不是把所有的电器都放在高处,直到断路器断开,我们需要打开另一个电器?我们是不是让洗碗机里放满了盘子,每次只拿出足够的东西来给新的脏盘子腾出空间?我们把所有的车都停在车道上直到——哦,没关系。

    如果用户想要最小化一个应用程序,那么最好是最小化它。如果一个用户想要退出一个应用程序,那么无论如何最好退出。

    它皱眉了吗?这是安卓的观点——他们不喜欢。许多独立的Android新手开发者对此深表不满。

    但是,当它归根结底,有好的编码和坏的编码。有好的程序流模型,也有坏的程序流模型。

    当用户知道程序已经完成时将它们留在内存中,这是不好的程序流。它完全没有任何作用,当启动新应用程序或运行应用程序分配更多内存时,它会减慢速度。

    它有点像你的车:有时你会让它继续运行,比如在停车灯前停车,或者在快餐店开车经过,或者在自动取款机前停车。但还有其他一些情况下你确实想把它关掉,比如当你去上班,或者去杂货店,甚至在家。

    同样,如果你在玩游戏,电话响了,是的。暂停游戏并继续运行。但是,如果用户在游戏中玩了一段时间,那么一定要让他们退出。

    某些应用程序上的"退出"按钮应该比其他应用程序前面更多。例如,用户可能希望完全退出的游戏或程序应该有一个明显的退出。其他程序,例如,可能是电子邮件程序,其中退出是不可能的愿望(以便它可以继续检查电子邮件)--这些程序不应浪费主控制输入屏幕空间与退出选项,但为了良好的程序流,它应该有退出选项。如果有人决定他们不想让他们的邮件程序在他们的覆盖率很低的时候检查电子邮件,或者在Skype电话或者其他什么的时候?如果他们愿意,让他们退出电子邮件程序!

    暂停和退出是两项重要任务,两项任务都不能完成另一项任务。


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

    例如,当应用程序不可见时,google listen会继续播放播客。但是当用户完成播客时,总是有一个暂停按钮来关闭它。如果我没记错的话,听我说,甚至在通知栏中放一个快捷方式,这样你就可以快速进入暂停按钮。另一个例子是像Twitter这样的应用程序,它经常在互联网上对服务进行投票。这些类型的应用程序应该真正允许用户选择轮询服务器的频率,甚至可以选择是否在后台线程中进行轮询。

    如果需要在退出时运行代码,可以根据需要重写onPause()、onStop()或onDestroy()。http://developer.android.com/reference/android/app/activity.html活动生命周期


    如果您无法理解如何使您的数据/连接(从而使您的"应用程序")持久化,那么您将无法使用Android做您"需要"做的事情。

    那些下载了这些可爱的小应用程序杀手的人通常会发现他们对电池寿命或内存使用没有帮助,但会阻碍操作系统有效地管理内存…

    http://android-developers.blogspot.com/2010/04/multitasking-android-way.html


    我会考虑阅读由Addison-Wesley出版的"Android无线应用程序开发"。我正在整理它,它很彻底。

    看来你对Android平台有一些根本的误解。起初,我对Android应用程序的应用程序生命周期也有点失望,但在更深入地了解之后,我开始真正享受这种方法。这本书将回答你所有的问题和更多的问题。它确实是我为新的Android开发者找到的最好的资源。

    另外,我认为您需要放弃现有应用程序的测线端口。为了将应用程序移植到Android平台,一些应用程序设计将发生变化。使用的应用程序生命周期是必要的,因为移动设备相对于桌面系统的资源非常有限,并且允许Android设备以一种有序和资源感知的方式运行多个应用程序。再深入研究一下这个平台,我想你会发现你想要做的是完全可行的。祝你好运。

    顺便说一句,我与艾迪生·韦斯利或任何与这本书相关的人或组织都没有任何关系。在重新阅读我的帖子后,我觉得自己有点狂热。我只是真的,真的很喜欢它,觉得它非常有帮助。:)


    几乎99%的时间不需要Android应用程序来接管自己的生命周期。大多数时候,归根结底是为了更好地规划或更智能地设计应用程序。例如,构建一个内部服务(不导出)来处理下载等,或者围绕用户工作流设计操作和任务。

    但有志者事竟成。Android通过ANDROID.OS.进程类提供了一个比Java更好的API来控制底层进程。与Java不同,它不把开发人员当作傻子对待,而是把它隐藏在一个简单的Java.Lang.Stuty.ExtTyter()调用之后。

    那么,你如何要求你的应用程序在Android中自杀呢?好吧,诀窍很简单:

    通过从标准android.app.application类继承来创建自己的android应用程序类(记住在androidmanifest.xml文件中声明它)。

    重写onCreate()方法,并存储启动应用程序的进程ID:

    1
    this.pid = android.os.Process.myPid(); // Save for later use.

    现在,要终止应用程序,请提供kill()方法:

    1
    android.os.Process.sendSignal(pid, android.os.Process.SIGNAL_KILL);

    现在,每当你需要你的应用程序去自杀的时候,只要输入cast应用程序上下文,然后调用kill方法!

    1
    ((MySuicidalApp) context.getApplicationContext()).kill()

    请记住,由于Android中的流程管理策略,特别是与服务相关的策略,Android可能会选择重新启动您的服务(请看,您不应该在Android上使用任务杀手)。


    当我想到Android中的应用程序时,我是这样看的:

    • 您正在处理您的应用程序
    • 电话铃响了。
    • 你接电话
    • 电话结束时,您回到原来的应用程序

    要做到这一点,您只需要手机上的XYKDBack按钮或home按钮(短按或长按)和通知栏。

    当我退出应用程序时,我只使用back按钮,直到我退出它或home按钮。

    我认为大多数应用程序就是这样构思的。但是如果我需要某种类型的会话或连接,我用一个登录/注销按钮和通知(标题栏或其他任何东西)向用户清楚地表明了这一点。这是一个与纯"退出"样式应用程序截然不同的样式。

    在PC上,你有一个多图形用户界面桌面,在Android上,你显然有多个任务,但你一次只显示一个应用程序(我不认为小工具在这里^)。在手机上,任何时候,你都可以收到一个比你正在做的事情更重要的通知。

    因此,应用程序的整个概念依赖于"进入应用程序-工作-退出应用程序"这一不同的东西。


    嗯…

    我认为你只是看不到Android应用程序的正确方式。你可以很容易地做你想做的事情:

    • 应用程序活动是否像开发人员LiveCycle文档中鼓励的那样保存/恢复状态?

    • 如果在恢复阶段需要一些登录(没有可用的登录/会话信息),则执行该操作。

    • 最后添加一个按钮/菜单/超时,在这种情况下,您将在不保存登录和其他会话信息的情况下执行finish(),从而隐式地结束应用程序会话:因此,如果应用程序再次启动/置于前端,它将启动一个新的会话。

    这样你就不会真正关心这个应用程序是否真的从内存中删除了。

    如果你真的想把它从记忆中删除(这是不鼓励的,顺便问一下是为了什么目的?)你可以有条件地在onDestroy()的末尾用java.lang.System.exit(0)杀死它(或者可能是restartPackage(..))。当然,只有在你想"真正结束应用程序"的情况下才这样做,因为onDestroy()是活动正常生命周期的一部分,而不是应用程序的结束。


    由于Android环境中的应用程序只是一堆模糊相关的活动,因此退出应用程序并没有多大意义。您可以完成()一个活动,并将绘制活动堆栈中上一个活动的视图。


    我同意泰德的观点。我了解退出应用程序不是"安卓方式",但似乎不应该排除。在这里您可能需要真正退出应用程序的三个原因(而不是只有活动):

  • 用户可能希望控制在内存不足。如果重要的应用程序A在后台运行,然后你可能想退出应用程序B当你完成了它,所以那个应用程序A不会被操作系统杀死。

  • 如果应用程序在内存中缓存了敏感数据,则可以喜欢杀掉这个应用程序,这样病毒/蠕虫/流氓应用程序就无法找到它。我知道安全模型应该可以防止这种情况,但是以防万一…

  • 如果应用程序使用资源(如网络、CPU、传感器等)这可能会对手机产生不利影响,然后确保释放这些资源是为了退出应用程序。我理解行为良好的应用程序应该在不需要时释放资源。但同样,退出应用程序似乎是确保这一点的合理方法。


  • Linux内核有一个称为内存不足杀手(如上所述,策略在用户空间级别是可配置的,而且内核不是最佳的,但决不是不必要的)。

    它被Android大量使用:

    • OOM杀手不适合用户空间

    • Android说明(OOM Killer信息-您可以在Android上配置OOM功能)

    • Android移植到真正的目标上

    一些用户空间应用程序可用于协助这些杀戮应用程序,例如:

    • Autokiller/配置Android的内部任务killer


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


    显然,您已经在finish()命令中找到了所需的答案。这不会从内存中删除你的应用程序,但只要Android需要资源,它就会这样做,所以你不会明确地这么做,这没有任何区别。

    我只想补充一点,为了获得应用程序退出通常具有的全部效果,您需要将应用程序的状态重置为设备启动后第一次运行时的正常状态,就在对所有活动调用finish()之前。这样,如果用户再次选择你的应用程序,它将看起来像是运行"新鲜",没有任何状态从模拟"退出"之前的点遗留下来。

    如果只有在"退出"时才会发生某些特殊操作,例如保存用户的工作或其他操作,则也可以在上述例程的重新初始化部分之前执行这些操作。

    这种方法允许您在不违反Android将操作系统资源(包括关闭应用程序)管理权交给操作系统的前提下实现"退出"命令的目标。

    就我个人而言,我不会使用这种方法,因为Android用户希望在重新访问应用程序时保持其连续性,因此他们不习惯"退出"应用程序的方式。相反,我支持一个"清除"功能,用户可以调用该功能将应用程序重置为某个默认初始状态,而不必在过程中"保留"它。

    唯一的例外是,当用户点击后退按钮足够多次以关闭应用程序时。在这种情况下,用户并不期望状态已经被保存(如果应用程序中有未保存的状态,那么作为开发人员,您应该让代码处理"后退"按钮来检测未保存的数据,并提示用户将其保存到sharedreferences或文件,或其他非易失性介质)。

    关于System.Exit(0):

    如果你决定使用system.exit(0)以粗暴的结尾关闭你的应用程序(例如,由于最后一次按下后退按钮),那么我会警告你,尽管对我来说这是"有效的",而且在某些情况下,这是我关闭应用程序的唯一方法,没有任何残留的痕迹,但当你使用这种方法。

    具体来说,如果使用"最近的应用程序"列表打开应用程序,然后使用"上一步"按钮关闭应用程序(通过System.Exit(0)实现关闭),则"最近的应用程序"列表将再次可见,因为它永远不会关闭。然后,如果您点击该列表中的应用程序条目,在同一个已打开的最近应用程序列表中再次运行它,则不会有任何响应。

    我怀疑造成这种情况的原因是最近的应用程序列表保留了对您的应用程序的引用,由于您已使用System.Exit(0)关闭了该应用程序,该引用已变得不起作用。使用finish()更文明地关闭应用程序可能会以一种方式通知操作系统,使其能够刷新其最近的应用程序列表,但system.exit(0)显然不会这样做。

    这本身并不是一个大问题,因为很少有人会从最近的应用程序中打开一个应用程序,然后退出它,然后立即从同一个打开的最近的应用程序列表中再次打开它。如果他们点击主页按钮,然后重新打开最近的应用程序列表,你的应用程序的条目就会出现在那里,它会完全正常工作。但我认为这表明使用system.exit(0)会干扰应用程序和操作系统之间的正确通信,这表明使用这种方法可能会产生其他更严重、可能更微妙的后果。


    有一个(相对)简单的设计,可以让你绕过"出口"难题。让你的应用程序有一个"基本"状态(活动),这只是一个空白屏幕。在第一次创建活动时,您可以启动应用程序的主要功能所在的另一个活动。"exit"可以通过finish()完成第二个活动并返回到一个空白屏幕的底部。操作系统可以在内存中保留这个空白屏幕,只要它想…

    本质上,因为你不能退出到操作系统,你只需转换成一个自我创造的虚无。


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

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


    首先,永远不要使用System.Exit(0)。就像让一个人睡觉打他的头!

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

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

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

    但要做到这一点,你必须学习并学习Android上的工作原理。无论如何,这是我为用户提供"退出按钮"的解决方案。

    我创建了一个选项菜单,在每个活动中始终可见(我有一个超级活动可以做到这一点)。

    当用户单击该按钮时,会发生以下情况:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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();

    所以我在保存共享的引用,我想杀死我的应用程序,我开始了一个意图。请看这些标志;这些标志将清除我的所有后台调用我的仪表板活动,这是我的"家"活动。

    因此,在我的仪表板活动中,我在onresume中运行此方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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的所有正确流程)时,应用程序仍在最近的活动中(但它是空白的)。

    似乎系统中仍存在最新的意图(已启动仪表盘活动)。

    我还得挖更多的东西才能把它移走。


    每次通过意图移动到下一页时,请使用:

    1
    `YourActivityname.this.finish()`;

    例子:

    1
    2
    3
    4
    Intent intent = new Intent(getApplicationContext(), SMS.class);

    startActivity(intent);
    MainActivity.this.finish();

    这样就不会在后台运行任何活动,当您想退出应用程序时,请使用:

    1
    2
    3
    4
    MainActivity.this.finish();
    android.os.Process.killProcess(android.os.Process.myPid());
    System.exit(0);
    getParent().finish();

    这种退出对我来说就像是一种魅力:)


    在任何时候关闭应用程序时,请先使用FLAG_ACTIVITY_CLEAR_TOP标记,然后使用system.exit();标记。

    或者有类似的方法,但如果不使用system.exit(),当您想退出时,调用此方法:

    1
    2
    3
    4
    public void exit() {
        startActivity(new Intent(this, HomeActivity.class).
        setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK).putExtra(EXIT_FLAG, true));
    }

    在您的HomeActivity.onCreate()中添加以下代码

    1
    2
    3
    4
    5
    6
    7
    protected void onCreate(Bundle savedInstanceState) {
        if (getIntent().getBooleanExtra(EXIT_FLAG, false)) {
            if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
                finish();
            }
        }
    ......................

    这将在不破坏Android生命周期的情况下工作。


    Android应用程序生命周期是为手机用户而非计算机用户设计的。

    应用程序生命周期是将Linux服务器转变为消费设备所需的极其简单的范例。

    Android是Linux上的Java,是一个真正的跨平台服务器操作系统。这就是它传播如此之快的原因。应用程序生命周期封装了操作系统的底层现实。

    对于移动用户,应用程序只是安装或未安装。没有运行或退出的概念。事实上,应用程序进程应该一直运行,直到操作系统释放它们以获取所持有的资源。

    由于这是堆栈溢出,任何阅读这篇文章的人都是计算机用户,必须关闭他们90%的知识才能理解移动应用程序的生命周期。


    阅读这个问答比实际实现半正确的Android应用程序生命周期要花更长的时间。

    这是一个GPS应用程序,它用一个线程每隔几秒钟对点进行轮询,并将当前位置发送到一个Web服务…这可能是在Ted的情况下每5分钟轮询一次更新,然后OnStop就可以简单地启动更新活动Ted担心是否找到了更新活动(异步Ted,不要像Windows程序员那样编码,否则您的程序将像Windows程序一样运行…嗯,没那么难)。

    我在OnCreate中做了一些初始代码来设置活动生命周期的内容,包括checkUpdate.start();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @Override
    public void onStart() {
        super.onStart();
        isRemote = true;
        checkUpdate.resume();

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, luh);
    }

    @Override
    public void onPause() {
        isRemote = false;
        checkUpdate.suspend();
        locationManager.removeUpdates(luh);
        super.onStop();
    }

    这个代码可能是完全错误的,但它是有效的。这是我的第一个Android应用程序。

    Voil_,一个在后台不消耗CPU的应用程序,但由于它在RAM中(虽然没有像Android生命周期那样保存RAM),所以可以立即重新打开……一个应用程序总是准备好的,它是一个电话,伙计们/姑娘们。如果一个应用程序耗尽了所有的内存,并且不能被操作系统关闭,那么事情可能会停止响铃=p这就是为什么操作系统需要能够在后台关闭你的应用程序(如果你的应用程序不是一个资源占用者,它不会被关闭btw),所以让我们编写更好的应用程序。


    在任何情况下,如果您想终止应用程序,可以随时调用System.exit(0);


    如果你有10,20……多个活动正在运行,您希望完成所有活动并退出系统。

    application classconstants class.中创建静态数组

    常量

    1
    2
    3
    4
    5
    public class Constants {

    public static ArrayList<Activity> activities = new ArrayList<Activity>();

    }

    mainActivity在此数组中添加当前活动引用

    activity = MainActivity.this;
    Constants.activities.add(activity);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    public class MainActivity extends Activity {

        private ImageView imageButton;
        private Activity activity;


        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            activity = MainActivity.this;
            Constants.activities.add(activity);

            imageButton = (ImageView) findViewById(R.id.camera);
            imageButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    // existing app.
                    if (Constants.activities != null) {
                        for (int i = 0; i < Constants.activities.size(); i++) {
                            Activity s = Constants.activities.get(i);
                            s.finish();
                        }
                    }
                    //super.finish();
                    finish();
                    android.os.Process.killProcess(android.os.Process.myPid());
                    System.exit(1);
                }
            });
        }
    }


    这很简单。请按照我将要告诉您的指示进行操作:

    就像你有多个活动一样,从一个活动转到另一个活动。您可能正在使用这样的意图:

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

    例如,在开始每个活动的意向活动后,您只需添加finish();,从开始到结束,

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

    因此,每当您单击使用finish()或system.exit(0)的退出按钮时,必须完全关闭应用程序。


    对于应用程序的第一个(开始)活动,

    1
    2
    3
    4
    5
    6
    @Override
    public void onBackPressed(){

        // Exit
        moveTaskToBack(true);
    }

    为我工作。我想在这里关闭应用程序。从其他活动中恢复过来;我使用意图,例如

    1
    2
    3
    4
    5
    6
    7
    8
    @Override
    public void onBackPressed(){

        // Going back....
        Intent intent = new Intent(ActivityB.this, ActivityA.class);
        startActivity(intent);
        finish();
    }

    注意:对于开发人员希望从activityz返回到activitya,然后关闭应用程序的场景,此代码非常有用。


    使用此代码:

    1
    2
    3
    4
    5
    Intent i = new Intent();
    i.setAction(Intent.ACTION_MAIN);
    i.addCategory(Intent.CATEGORY_HOME);
    ListActivity.this.startActivity(i);
    finish();


    目前我在我的应用程序中实现了以下功能。希望这些帮助您从应用程序中移出任何您想要的地方。我从操作栏菜单调用这个函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    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);
    }

    你可以使用Process.killProcess(Process.myPid());来终止你的应用程序,但它可能不安全?使用此方法后,我没有遇到任何问题或崩溃,使用此方法后,我的应用程序在DDMS列表中的进程消失。


    另一种选择是Android可访问性服务,它使应用程序绿色化,以强制关闭应用程序以加速内存。通过让应用程序辅助功能服务访问,您可以单击按钮,使应用程序基本上绿色化,单击应用程序设置中的强制关闭按钮:

    您可以在这里学习无障碍服务:https://developer.android.com/reference/android/accessibilityservice/accessibilityservice.html

    以下是辅助服务程序单击的设置按钮:enter image description here

    因此,您可以通过以下步骤杀死任何应用程序,包括您的应用程序:

    1)无障碍服务登记申请2)根据您的要求,如果您想终止所有应用程序,请获取所有包的列表。3)导航至其设置屏幕,然后单击强制关闭按钮。就是这样。我可以共享一个示例代码,我还创建了一个像greenify这样的应用程序作为家庭作业。谢谢你

    更新:用户没有,系统会自动处理。因此,基本上,通过这个解决方案,我们间接地使用系统强制关闭,但是根据用户的需求。这样双方都能保持快乐


    如果指定api>=16,则activity finishAffinity()满足您的需要。


    使用"退出"按钮的一个重要原因是"退出时"广告。在出口处,可以显示一些创收广告。它仍然有点烦人,就像所有的广告一样,但可能比那些一直在使用宝贵的屏幕空间的东西更不烦人。一些广告网络提供这种广告方式。但是,事实上,你不能只放一个退出按钮,在显示广告后什么都不做!

    因此,在某些情况下需要一种或另一种终止程序的方法,而"不应该被需要"可能不是最全面的答案。

    可以使用activity.finish()或system.exit(0)。