【Android】使用UncaughtExceptionHandler捕获全局异常
简介
当程序崩溃(Crash)的时候,默认是不对异常信息做处理的。如果想要把异常信息保存到本地文件中,或上传的服务器。那么就要借助UncaughtExceptionHandler
这个类。
使用方法
一、实例化
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| public class CrashLogCatch { public static final String THREAD_NAME_MAIN = "com.example.ABC"; public static final String THREAD_NAME_REMOTE = "com.example.ABC:remote_service"; public static void initCrashLog(final Context context) { final Thread.UncaughtExceptionHandler oriHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread thread, Throwable e) { try { StringBuilder buffer = new StringBuilder(); buffer.append(getCurProcessName(context) + "\n"); buffer.append("uncaught exception at ") .append(new Date(System.currentTimeMillis())) .append("\n"); buffer.append(ExceptionUtils.formatException(e)); String log = HttpLogController.getInstance().makeCrashLog(buffer.toString()); sendExceptionLog(log); SdLog.dFileAlways("crash" + System.currentTimeMillis() + ".log", log); if (Global.DEBUG) { oriHandler.uncaughtException(thread, e); } else { String threadName = thread.getName(); if (threadName.equals(THREAD_NAME_REMOTE)) { android.os.Process.killProcess(android.os.Process.myPid()); } else if (threadName.equals(THREAD_NAME_MAIN)) { oriHandler.uncaughtException(thread, e); } } } catch (Exception ex) {} } }); }
private static String getCurProcessName(Context context) { try { int pid = android.os.Process.myPid(); ActivityManager mActivityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) { if (appProcess.pid == pid){ return appProcess.processName; } } } catch (Exception e) { e.printStackTrace(); } return ""; }
private static void sendExceptionLog(String log) { try { JSONObject jsonObject = new JSONObject(log); Iterator keyIter = jsonObject.keys(); String key; Object value; HashMap<String, Object> valueMap = new HashMap<String, Object>(); while (keyIter.hasNext()) { key = (String) keyIter.next(); value = jsonObject.get(key); valueMap.put(key, value); } ComponentHolder.getLogController().sendLog(valueMap, LogType.EXCEPTION); } catch (JSONException e) { e.printStackTrace(); } } }
|
二、调用
1、对于整个Application
只要在指定的Application类的onCreate()回调中,把UncaughtExceptionHandler和Application的实例绑定在一起就可以了。关键代码如下:
1 2 3 4 5 6 7 8
| public class MyApplication extends Application {
@Override public void onCreate() { CrashLogCatch.initCrashLog(this); super.onCreate(); } }
|
这样,如果程序崩溃,错误日志就会被上传到服务器。
2、绑定Service 实例
1 2 3 4 5 6 7 8
| public class MyService extends Service {
@Override public void onCreate() { Thread.currentThread().setName(CrashLogCatch.THREAD_NAME_REMOTE); CrashLogCatch.initCrashLog(this); } }
|
3、绑定BroadcastReceiver实例
1 2 3 4 5 6 7 8
| public class LaunchReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) { Thread.currentThread().setName(CrashLogCatch.THREAD_NAME_REMOTE); CrashLogCatch.initCrashLog(context); } }
|
参考资料