`
263229365
  • 浏览: 472109 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

android——彻底关闭——应用程序

 
阅读更多

 

最近学习做android的游戏开发时候,发现一个关于android退出时不能彻底关闭的问题,比如:一个程序里new 出了N多个Thread,这样在退出程序的可能不能完全关闭,最后发现,只用finish()方法,有时候不能彻底退出,个人感觉还是要在适当的地方加上:System.exit(0);

-=====-=-=-=-=-=======-----=====

 

1. finish()方法

该方法可以结束当前 Activity,但是如果你的App有很多 Activity 的话,使用该方法显得有点捉襟见肘了。

另外,还有一个方法finishActivity (int requestCode) ,关于这个方法,先看看sdk的api说明吧!

 

  1. public void finishActivity (int requestCode)  
  2. Since: API Level 1  
  3. Force finish another activity that you had previously started with startActivityForResult(Intent, int).  
  4. Parameters requestCode  The request code of the activity that you had given to startActivityForResult(). If there are multiple activities started with this request code, they will all be finished.  

 

也许你会这样理解 ,Activity1 通过方法 startActivityForResult (Intent, int) 启动 Activity2,然后在 Activity2 中通过方法finishActivity (int requestCode)来结束 Activity1,但是很不幸运,不是这样的。不信你可以Demo一把! 

上面文档说得很明白,该方法强制关闭通过方法 startActivityForResult (Intent, int) 启动的 Activity,也就是说在 Activity1 中的(重写)方法onActivityResult(int requestCode, int resultCode, Intent data) 来接收 Activity2 返回的结果,必须在 Activity1 中调用finishActivity (int requestCode)来结束 Activity2。(一般在onActivityResult 方法调用该方法结束 Activity2)。

 

  1. Force finish another activity that you had previously started with startActivityForResult(Intent, int).  
  2. Parameters  

还有,下面两个方法,可以参阅文档以及源码研究一下。

 

 

  1. finishActivityFromChild(Activity child, int requestCode)  
  2. finishFromChild(Activity child)  

 

2. killProcess

通过调用 android.os.Process 的相关方法,结束 App,示例如下:

 

  1. btn_exit.setOnClickListener(new Button.OnClickListener() {  
  2.     @Override  
  3.     public void onClick(View v) {  
  4.         android.os.Process.killProcess(android.os.Process.myPid());  
  5.     }  
  6.       });  
 

 

3. exit

我们知道,Java 的 exit(int code) 方法可以退出程序,通过查看该方法源码,知道它实际上是调用下面的方法:

 

  1. Runtime.getRuntime().exit(code);  
 

 

示例代码,如下所示:

 

  1. btn_exit.setOnClickListener(new Button.OnClickListener() {  
  2.             @Override  
  3.             public void onClick(View v) {  
  4.                 System.exit(0);//正常退出App  
  5.             }  
  6.         });  
 

 

接下来,我们研究一下这个方法。java.lang.System这个类的该方法jdk说明:

 

  1. exit  
  2.   
  3. public static void exit(int status)  
  4. 终止当前正在运行的 Java 虚拟机。参数用作状态码;根据惯例,非 0 的状态码表示异常终止。  
  5. 该方法调用 Runtime 类中的 exit 方法。该方法永远不会正常返回。  
  6.   
  7. 调用 System.exit(n) 实际上等效于调用:  
  8.   
  9.  Runtime.getRuntime().exit(n)  
  10.    
  11. 参数:  
  12. status - 退出状态。  
  13. 抛出:  
  14. SecurityException - 如果安全管理器存在并且其 checkExit 方法不允许以指定状态退出。  
  15. 另请参见:  
  16. Runtime.exit(int)  

也就是说,参数为非0值的话是异常退出程序。参数为0的话,就是正常退出。

 

看RunTime这个类的该方法源码:

 

  1. public void exit(int status) {  
  2.         SecurityManager security = System.getSecurityManager();  
  3.     if (security != null) {  
  4.         security.checkExit(status);  
  5.     }  
  6.     Shutdown.exit(status);  
  7. }  

其api说明:

 

 

  1. exit  
  2.   
  3. public void exit(int status)  
  4. 通过启动虚拟机的关闭序列,终止当前正在运行的 Java 虚拟机。此方法从不正常返回。可以将变量作为一个状态码;根据惯例,非零的状态码表示非正常终止。  
  5. 虚拟机的关闭序列包含两个阶段。在第一个阶段中,会以某种未指定的顺序启动所有已注册的关闭钩子 (hook)(如果有的话),并且允许它们同时运行直至结束。在第二个阶段中,如果已启用退出终结,则运行所有未调用的终结方法。一旦完成这个阶段,虚拟机就会暂停。  
  6.   
  7. 如果在虚拟机已开始其关闭序列后才调用此方法,那么若正在运行关闭钩子,则将无限期地阻断此方法。如果已经运行完关闭钩子,并且已启用退出终结 (on-exit finalization),那么此方法将利用给定的状态码(如果状态码是非零值)暂停虚拟机;否则将无限期地阻断虚拟机。  
  8.   
  9. System.exit 方法是调用此方法的一种传统而便捷的方式。  
  10.   
  11. 参数:  
  12. status - 终止状态。按照惯例,非零的状态码表明非正常终止。  
  13. 抛出:  
  14. SecurityException - 如果安全管理器存在,并且其 checkExit 方法不允许存在指定的状态  
  15. 另请参见:  
  16. SecurityException, SecurityManager.checkExit(int), addShutdownHook(java.lang.Thread), removeShutdownHook(java.lang.Thread), runFinalizersOnExit(boolean), halt(int)  

该方法又是调用Shutdown这个类的exit()方法。

  1. static void exit(int status) {  
  2.     boolean runMoreFinalizers = false;  
  3.     synchronized (lock) {  
  4.         if (status != 0) runFinalizersOnExit = false;  
  5.         switch (state) {  
  6.         case RUNNING:   /* Initiate shutdown */  
  7.         state = HOOKS;  
  8.         break;  
  9.         case HOOKS:     /* Stall and halt */  
  10.         break;  
  11.         case FINALIZERS:  
  12.         if (status != 0) {  
  13.             /* Halt immediately on nonzero status */  
  14.             halt(status);  
  15.         } else {  
  16.             /* Compatibility with old behavior: 
  17.              * Run more finalizers and then halt 
  18.              */  
  19.             runMoreFinalizers = runFinalizersOnExit;  
  20.         }  
  21.         break;  
  22.         }  
  23.     }  
  24.     if (runMoreFinalizers) {  
  25.         runAllFinalizers();  
  26.         halt(status);  
  27.     }  
  28.     synchronized (Shutdown.class) {  
  29.         /* Synchronize on the class object, causing any other thread 
  30.              * that attempts to initiate shutdown to stall indefinitely 
  31.          */  
  32.         sequence();  
  33.         halt(status);  
  34.     }  
  35.     }  

其中,runAllFinalizers()是一个本地方法:

 

 

  1. JNIEXPORT void JNICALL  
  2. Java_java_lang_Shutdown_runAllFinalizers(JNIEnv *env, jclass ignored)  
  3. {  
  4.     jclass cl;  
  5.     jmethodID mid;  
  6.   
  7.     if ((cl = (*env)->FindClass(env, "java/lang/ref/Finalizer"))  
  8.     && (mid = (*env)->GetStaticMethodID(env, cl,  
  9.                         "runAllFinalizers""()V"))) {  
  10.     (*env)->CallStaticVoidMethod(env, cl, mid);  
  11.     }  
  12. }  

System.exit()的参数是把退出原因返回给系统, 一般来说可以是任何的整数 。

0表示正常退出,1表示非正常 。

 

最后说一下finish()与exit方法的区别:

finish()是Activity的类方法,仅仅针对Activity,当调用finish()时,只是将活动推向后台,并没有立即释放内存,活动的资源并没有被清理;当调用System.exit(0)时,退出当前Activity并释放资源(内存),但是该方法不可以结束整个App如有多个Activty或者有其他组件service等不会结束。

其实android的机制决定了用户无法完全退出应用,当你的application最长时间没有被用过的时候,android自身会决定将application关闭了。


4. restartPackage方法

  1. ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);      
  2. manager.restartPackage(getPackageName());  

 

首先需要创建ActivityManager对象,然后调用restartPackage()方法(如果有兴趣的话,可以看源码)。

注意:getPackageName获得当前应用包名称,如mark.zhang

使用这种方式来退出App,需要权限:

 

  1. <uses-permission android:name="android.permission.RESTART_PACKAGES" />  

更加详细的说明,如下:

 

  1. void android.app.ActivityManager.restartPackage(String packageName)  
  2.   
  3. Have the system perform a force stop of everything associated with the given application package. All processes that share its uid will be killed, all services it has running stopped, all activities removed, etc. In addition, a Intent.ACTION_PACKAGE_RESTARTED broadcast will be sent, so that any of its registered alarms can be stopped, notifications removed, etc.  
  4.   
  5. You must hold the permission android.Manifest.permission.RESTART_PACKAGES to be able to call this method.  
  6.   
  7. Parameters:  
  8.     packageName The name of the package to be stopped.  

可以看出,相同的UID的进程会被kill,还会停止相关的服务以及移除所有的Activity,并且会发送一个广播。


注意一个问题:在android2.2之后,该方法不可以将应用程序结束,需要使用ActivityManager类的下面这个方法:

 

  1. public void killBackgroundProcesses (String packageName)  

api 文档说的很清楚:

 

 

  1. public void restartPackage (String packageName)  
  2.   
  3. Since: API Level 3  
  4. This method is deprecated.  
  5. This is now just a wrapper for killBackgroundProcesses(String); the previous behavior here is no longer available to applications because it allows them to break other applications by removing their alarms, stopping their services, etc.  

另外,需要使用权限:

 

 

  1. <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>   

 

但是不管你怎么样折腾,还是无法退出App,呜呼哀哉!这里给出一个方法:

 

  1. int currentVersion = android.os.Build.VERSION.SDK_INT;  
  2.             if (currentVersion > android.os.Build.VERSION_CODES.ECLAIR_MR1) {  
  3.                 Intent startMain = new Intent(Intent.ACTION_MAIN);  
  4.                 startMain.addCategory(Intent.CATEGORY_HOME);  
  5.                 startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  6.                 startActivity(startMain);  
  7.                 System.exit(0);  
  8.             } else {// android2.1  
  9.                 ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);  
  10.                 am.restartPackage(getPackageName());  
  11.             }  


关于android.os.Build.VERSION.SDK_INT,可以参考 http://blog.csdn.net/androidbluetooth/article/details/6778422

 


5. 小结


finish():结束当前Activity,不会立即释放内存。遵循android内存管理机制。


exit():结束当前组件如Activity,并立即释放当前Activity所占资源。


killProcess():结束当前组件如Activity,并立即释放当前Activity所占资源。


restartPackage():结束整个App,包括service等其它Activity组件。


特别注意:除了finish()方法可以调用Activity的生命周期方法如onStop()、onDestroy(),其余三种退出App均不会调用Activity的生命周期方法。除非,在调用这几个方法之前或者之后主动调用Activity的生命周期方法。如:

  1. System.exit(int);  
  2. onDestroy();  

<!--EndFragment-->

分享到:
评论

相关推荐

    Android——okhttp的封装

    Android——okhttp的封装,Android——okhttp的封装,Android——okhttp的封装,Android——okhttp的封装,Android——okhttp的封装

    深入浅出Android——Google手持设备应用程式设计

    《深入浅出Android——Google手持设备应用程式设计》是一本专为Android开发者量身打造的实战指南,旨在通过丰富的实例解析,帮助读者深入理解和掌握Android应用程序的开发技术。这本书覆盖了Android开发的基础到高级...

    移动操作系统原理与实践——基于Java语言的Android应用开发.zip

    移动操作系统原理与实践——基于Java语言的Android应用开发 目录 基础篇 第1章移动操作系统概论 1.1操作系统的原理与概念 1.1.1隐藏硬件细节 1.1.2资源管理 1.1.3操作系统的历史 1.2操作系统的分类 1.2.1...

    android——多线程

    标题"android——多线程"和描述"android——Handler与多线程应用范例"暗示我们将深入探讨如何在Android中使用Handler来管理多线程。 Android系统默认运行在一个单线程环境中,即主线程,也被称为UI线程。主线程主要...

    Android——本息计算器

    【Android——本息计算器】是一个基于Android平台的计算器应用,主要功能是帮助用户计算贷款的本息情况。在金融领域,此类计算器对于个人理财和企业管理都具有很高的实用价值。通过这款应用,用户可以输入贷款金额、...

    Android源码——数据库SQLite.zip

    此外,Android还提供了一个更高级的API——ContentProvider,它允许不同应用程序间共享数据。ContentProvider基于SQLite数据库,提供了一种统一的接口,使得数据的访问更加安全和规范。如果你的应用程序需要与其他...

    深入浅出Android——Android开发经典教材

    4. 程序流程的解读与实践:通过对程序流程的解读,让读者理解Android应用是如何运行的,并通过实际编码完成BMI(Body Mass Index,体质指数)程序来加深理解。 5. Android应用组件的使用和生命周期:介绍Android中...

    AndroidStudio————实战演练——仿美团外卖菜单

    在本项目中,"AndroidStudio————实战演练——仿美团外卖菜单"是一个专注于使用Android Studio开发的应用程序实战案例,目标是创建一个类似于美团外卖的菜单功能。这个项目涵盖了多个Android开发的关键知识点,...

    [Android Studio应用开发——基础入门与应用实战][方欣,杨勃][电子课件]

    【Android Studio应用开发——基础入门与应用实战】是针对初学者和希望提升Android应用程序开发技能的人群设计的一门课程。这门课程由专家方欣和杨勃共同编写,旨在通过电子课件的形式,深入浅出地讲解Android ...

    安卓Android源码——模仿乐淘的应用程序分析源码.zip

    本资源"安卓Android源码——模仿乐淘的应用程序分析源码.zip"提供了一个仿制乐淘电商平台的源代码,这对于学习如何构建类似应用的开发者来说是一份宝贵的学习材料。通过分析这份源码,我们可以了解一个完整的安卓...

    Android源码——笑话故事android应用源码.7z

    【标题】"Android源码——笑话故事android应用源码.7z" 提供的是一个基于Android平台开发的笑话故事应用程序的源代码。这个项目可能是为了帮助开发者了解如何在Android环境中构建一个用户友好的娱乐应用,它可能包含...

    基于Android ——MyDate 好看的日历,效果明显。.rar

    .rar" 这个标题表明我们关注的是一个Android平台上的应用,名为MyDate,它是一款设计美观、显示效果显著的日历应用。从标题我们可以推测,这个压缩包可能包含了该日历应用的源代码、资源文件、设计文档或者是演示...

    android应用小程序———计算器源码

    这个"android应用小程序———计算器源码"就是一个完整的实例,展示了如何使用MyEclipse这一集成开发环境(IDE)来构建一个功能完备的Android计算器。这份源码对于初学者或有经验的开发者来说,都是一个很好的学习和...

    Android三维程序设计——基于OpenGL ES的图形应用程序设计——(源码)

    Android三维程序设计——基于OpenGL ES的图形应用程序设计——(源码) 英文版《Learn-OpenGL-ES-Master》

    安卓Android源码——android相册系统(用Matrix实现).zip

    这个压缩包文件"安卓Android源码——android相册系统(用Matrix实现).zip"包含了一个使用Matrix类来实现的相册系统源码。Matrix是Android图形库中的一个关键类,它允许开发者对图像进行平移、旋转、缩放等变换操作。...

    Android源码——掌上几分钟视频应用源码.zip

    【Android源码——掌上几分钟视频应用源码.zip】是一个包含Android应用程序源代码的压缩文件,主要用于学习和研究Android平台上短视频应用的开发。这个源码提供了掌上几分钟视频应用的完整实现,帮助开发者深入理解...

    安卓Android源码——重力感应跑步测速应用.zip

    这款名为"安卓Android源码——重力感应跑步测速应用"的项目,提供了实现这一功能的完整源码,非常适合对移动开发感兴趣的开发者进行学习和研究。在这个项目中,我们可以深入理解如何将Android的硬件传感器API与用户...

    Android源码——笑话故事android应用源码.zip

    【Android源码解析——构建笑话故事应用】 在深入解析这个"Android源码——笑话故事android应用源码.zip"之前,我们需要了解Android应用的基本结构和开发流程。Android应用主要由Java或Kotlin语言编写,通常包括...

Global site tag (gtag.js) - Google Analytics