自己定义Application的未捕获异常处理

近期由于工作原因。进行Android应用开发时发现应用在出现类似空指针等异常时,抛出未被捕获的异常。Android系统有默认的未捕获异常处理器,默认行为是结束对应的线程,但并不会直接退出程序,并且在应用还有后台Service时。服务还一直在执行,假设service在请求网络时还会抛出一些异常信息,并且在未全然退出的应用中再次使用还会进一步导致异常,这样对于用户体验来说实在不好。

因此,须要在应用无论什么情况下出现异常后应该直接退出应用,然后重新启动应用。网上搜了非常多资料。非常多都不能非常好解决问题,由于Android可能会启动非常多Activity,而在结束应用进程之前应该finish全部Task中的Activity,否则会出现一些不想要的结果,当然还要结束后台的Service。

Android中有一个Thread.UncaughtExceptionHandler接口,须要实现该接口。并实现当中的uncaughtException函数。以下直接贴上相关代码:

public class MyCrashHandler implements Thread.UncaughtExceptionHandler {

private static final String TAG = "MyCaughtException";

// 应用

private MyApplication mApplication;

// 系统默认的未捕捉异常处理器

private Thread.UncaughtExceptionHandler mDefaultHandler;

// 自己定义的未捕捉异常处理器

private static MyCrashHandler gCaughtException;

/**

* 单例模式的保障

*/

private CEPM360CrashHandler() {

}

/**

* 单例模式

* @param application

* @return

*/

public static synchronized MyCrashHandler getInstance(Application application) {

if (gCaughtException == null) {

gCaughtException = new MyCrashHandler(application);

}

return gCaughtException;

}

/**

* 构造函数

* @param application

*/

private MyCrashHandler(Application application) {

mApplication = (MyApplication) application;

// 获取系统默认的UncaughtExceptionHandler

mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

// 设置异常处理器

Thread.setDefaultUncaughtExceptionHandler(this);

}

/**

* 未捕获异常处理函数

*/

@Override

public void uncaughtException(Thread thread, Throwable ex) {

Log.e(TAG, "Ocurrs uncaughtException!");

// 打印堆栈

ex.printStackTrace();

Intent intent = new Intent(mApplication, MyService.class);

if (!handleException(ex) && mDefaultHandler != null) {

mDefaultHandler.uncaughtException(thread, ex);

} else {

try {

mApplication.stopService(intent);

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

// 退出程序后,启动应用第一个LoginActivity

intent = new Intent(mApplication, MainActivity.class);

PendingIntent restartIntent =

PendingIntent.getActivity(mApplication,

0,

intent,

Intent.FLAG_ACTIVITY_NEW_TASK);

AlarmManager alarmManager = (AlarmManager)

mApplication.getSystemService(Context.ALARM_SERVICE);

alarmManager.set( AlarmManager.RTC,

System.currentTimeMillis() + 1000,

restartIntent);

mApplication.exit();

}

/**

* 异常处理函数

* @param ex

* @return

*/

private boolean handleException(Throwable ex) {

if (ex == null) {

return false;

}

// 重新启动一个线程显示异常信息

new Thread() {

@Override

public void run() {

Looper.prepare();

showExceptionToast();

Looper.loop();

}

}.start();

return true;

}

/**

* 显示发生异常Toast,确认后重新启动应用

*/

private void showExceptionToast() {

Toast toast = Toast.makeText(mApplication,

"非常抱歉,“CEPM360”已停止执行,即将重新启动", Toast.LENGTH_SHORT);

// 设置居中显示

toast.setGravity(Gravity.CENTER, 0, 0);

LinearLayout toastLayout = (LinearLayout) toast.getView();

toastLayout.setLayoutDirection(LinearLayout.HORIZONTAL);

ImageView image = new ImageView(mApplication);

image.setImageResource(R.drawable.exception_picture);

toastLayout.addView(image, 0);

toast.setView(toastLayout);

toast.show();

}

}

上面是自己定义的未捕获异常处理器。要想让其发挥作用,须要配合Application,默认情况下Android不须要你手动实现或实例化一个APPlication对象。但自己定义未捕获异常处理中要finish全部的activity。但在application中没有对应的Task相关API,就没有办法拿到当前应用在Task中的全部Activity,因此须要我们自己实现一个Application类,并维护一个Activity列表,当启动一个Activity时将其增加该列表,当出现未捕获异常时,会逐一finish掉这里的全部Activity。

public class MyApplication extends Application {

// Activity列表,用来全然退出应用

private List<Activity> mActivities = new ArrayList<Activity>();

// 共享数据

private Map<String, Object> mAppSharedData = new HashMap<String, Object>();

@Override

public void onCreate() {

super.onCreate();

MyCrashHandler.getInstance(this);

}

/**

* 获取应该共享数据

* @return

*/

public Map<String, Object> getAppSharedData() {

return mAppSharedData;

}

/**

* 加入一个共享Map元素

* @param map

*/

public void addSharedData(Map<String, Object> map) {

mAppSharedData.putAll(map);

}

/**

* 加入一个共享元素

* @param string

* @param object

*/

public void addSharedData(String string, Object object) {

mAppSharedData.put(string, object);

}

/**

* 获取共享元素值

* @param string

* @return

*/

public Object getValue(String string) {

return mAppSharedData.get(string);

}

/**

* 当启动一个activity时,加入到该列表中

* @param activity

*/

public void addActivity(Activity activity) {

mActivities.add(activity);

}

/**

* 退出应用

*/

public void exit() {

// 循环退出Activity

try {

for (Activity activity : mActivities) {

if (activity != null)

activity.finish();

}

} catch (Exception e) {

e.printStackTrace();

} finally {

// 最后退出虚拟机

System.exit(0);

}

}

@Override

public void onLowMemory() {

super.onLowMemory();

System.gc();

}

}

上面的mAppSharedData映射表是用于应用的数据共享,不是本文讨论重点。这里重点指出:在MyCrashHandler 中的uncaughtException函数中完毕异常的全部处理。包含停止Service和Activity。在发送重新启动广播之后,退出虚拟机。这里也能够使用以下的代码:

android.os.Process.killProcess(android.os.Process.myPid());

时间: 2024-10-14 17:01:01

自己定义Application的未捕获异常处理的相关文章

自定义Application的未捕获异常处理

最近因为工作原因,进行Android应用开发时发现应用在出现类似空指针等异常时,抛出未被捕获的异常,Android系统有默认的未捕获异常处理器,默认行为是结束相应的线程,但并不会直接退出程序,而且在应用还有后台Service时,服务还一直在运行,如果service在请求网络时还会抛出一些异常信息,而且在未完全退出的应用中再次使用还会进一步导致异常,这样对于用户体验来说实在不好. 因此,需要在应用不管什么情况下出现异常后应该直接退出应用,然后重启应用.网上搜了很多资料,很多都不能很好解决这个问题,

解析服务器实时查询错误:未捕获TypeError:无法读取属性的onNext定义

服务器是完全设置但在客户端代码 let query = new Parse.Query('Notification');let subscription = query.subscribe();subscription.on('open', () => {console.log('subscription opened');});抛出错误: 未捕获TypeError:无法读取属性"onNext"定义的订阅. 第3894行 第3894行 key: 'pushData', value

Dream------scala--函数定义、流程控制、异常处理

Dream------scala--函数定义.流程控制.异常处理 一.函数的定义 1.新建工程 2.创建一个object package com.wls.scala.hello /** * Created by wls on 2015年8月11日21:06:332. */ object ScalaBasics { def main(args : Array[String]): Unit ={ } } def main(args : Array[String]) : Unit={} 上面这个就项目

Android中使用UncaughtExceptionHandler来处理未捕获的异常

原文在sparkyuan.me上,转载注明出处:http://sparkyuan.github.io/2016/03/28/使用UncaughtExceptionHandler来处理未捕获的异常/ 所有的App都会发生crash,本文讲解的是如何采集crash信息以供后续开发处理这类问题. 基本思路 当crash发生时,系统会调用UncaughtExceptionHandler的uncaughtException方法,我们可以在这个方法中捕获异常信息,把异常信息存到SD卡中,在合适的时候通过网络

Scala-02函数定义、流程控制、异常处理

scala-02函数定义.流程控制.异常处理 一.Scala函数定义: (scala函数定义时候默认会导入包) (1)val:类似java中final类型的变量(常量) 1,基本格式:val 变量名:变量类型 = 值 2,其中有时变量类型可以省略,可以自动识别 3,变量不能赋值,修改 var :等同于java中的非final型变量 (2)有参数的函数定义 def 函数名(参数列表,...):返回结果类型={} Object MyScala{ def Mysca(x:int ,y:int):int

从大数据菜鸟走上大师的历程 第二讲:函数定义,流程控制,异常处理

Scala 第二讲 函数定义,流程控制,异常处理 For 循环  for(左边为单个对象obj  <-  右边为对象集合objs ) for 循环里把右边的对象赋给左边 现在正是学习大数据的最好机遇,不花一分钱就可以成为大数据高手,实现年薪50万的梦想. 王家林的第一个中国梦:免费为全社会培养100万名优秀的大数据从业人员! 如果您有兴趣请点击这个链接进入大数据的学习 http://blog.sina.com.cn/s/blog_8fbd39ee0102vto3.html 如果您确实感觉视频教程

Scala深入浅出实战经典-----002Scala函数定义、流程控制、异常处理入门实战

002-Scala函数定义.流程控制.异常处理入门实战 Scala函数定义 语句结束无分号 定义无参函数 def 函数名称(参数名称:参数类型)[:Unit=]{ 函数体 } 老师的代码 我的实际代码 原因是集成开发环境自带的版本为2.11.0 变量 常量(不可变)声明 val 变量声明 var 无参函数的调用也无需加括号() 定义有参有返回值的函数 def 函数名称(参数名称:参数类型...):返回值类型={ 函数体 } 老师代码 注意最后一个是b是本函数的返回值 默认最后一行为返回值 流程控

Scala深入浅出实战经典-----002-Scala函数定义、流程控制、异常处理入门实战

002-Scala函数定义.流程控制.异常处理入门实战 Scala函数定义 语句结束无分号 定义无参函数 def 函数名称(参数名称:参数类型)[:Unit=]{ 函数体 } 老师的代码 我的实际代码 原因是集成开发环境自带的版本为2.11.0 变量 常量(不可变)声明 val 变量声明 var 无参函数的调用也无需加括号() 定义有参有返回值的函数 def 函数名称(参数名称:参数类型...):返回值类型={ 函数体 } 老师代码 注意最后一个是b是本函数的返回值 默认最后一行为返回值 流程控

002-Scala函数定义、流程控制、异常处理入门实战

002-Scala函数定义.流程控制.异常处理入门实战 Scala函数定义 语句结束无分号 定义无参函数 def 函数名称(参数名称:参数类型)[:Unit=]{ 函数体 } 老师的代码 我的实际代码 原因是集成开发环境自带的版本为2.11.0 变量 常量(不可变)声明 val 变量声明 var 无参函数的调用也无需加括号() 定义有参有返回值的函数 def 函数名称(参数名称:参数类型...):返回值类型={ 函数体 } 老师代码 注意最后一个是b是本函数的返回值 默认最后一行为返回值 流程控