UncaughtExceptionHandler
为了捕获没有被捕获的异常,包括运行时异常,执行错误(内存溢出等),子线程抛出的异常等。
1. 创建一个类 CrashHandler 实现 UncaughtExceptionHandler 接口 , 当程序发生未捕获异常时 由该类进行处理
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler mDefaultHandler;
Context context;
//CrashHandler实例
private static CrashHandler instance;
/**
* 获取CrashHandler实例 ,单例模式
*/
public static CrashHandler getInstance() {
if (instance == null)
instance = new CrashHandler();
return instance;
}
/**
* 初始化
*/
public void init(Context context) {
this.context = context;
//获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
//设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
//实现uncaughException方法
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!solveException(ex) && mDefaultHandler != null) {
//如果用户没有处理则让系统默认的异常处理器处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
// 等待2秒钟后关闭程序
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
/*
* 错误处理
* */
private boolean solveException(Throwable e) {
if (e == null) {
return false;
}
new Thread() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(context, "程序出现异常,2秒后退出", Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
return true;
}
}
2. 创建一个基础Application的类MApplication
在onCreate()方法中进行初始化
CrashHandler.getInstance().init(getApplicationContext());
多进程可能内存在问题
发生crash后,通过uncaughtException或killApp,只对当前进程进行了重启或杀死,其他进程仍存在。
/**
* 杀死除当前进程的其他进程
*/
@SuppressWarnings("WeakerAccess")
public static void killProcessExceptCurrent(@NonNull Context context) {
Log.e(TAG, "killProcessExceptCurrent");
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (am == null) {
return;
}
List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
if (runningApps == null) {
return ;
}
for (ActivityManager.RunningAppProcessInfo proInfo : runningApps) {
if (proInfo.processName.startsWith(HiApplication.context.getPackageName())
&& proInfo.pid != android.os.Process.myPid()) {
Log.e(TAG, "killProcessExceptCurrent kill: " + proInfo.processName);
android.os.Process.killProcess(proInfo.pid);
}
}
}
PS:
https://blog.csdn.net/axi295309066/article/details/56123954
android6.0以上的getRunningAppProcesses也失效,出于安全考虑系统关闭了三方软件对系统进程的访问。
网友评论