【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);    	} }
  | 
 
参考资料