當app釋出到市場,使用者下載使用過程中如果出現crash的情況,對使用者來說是非常不友好,有可能使用者直接把應用給解除安裝了。因此捕獲以及分析crash對我們來說至關重要,讓我們及時修復異常,減少使用者流失。
定義crash處理類CrashHandler,並且實現Thread.UncaughtExceptionHandler介面
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private final String PATH = "error";
private Context mContext;
private Thread.UncaughtExceptionHandler mUncaughtExceptionHandler;
public void init(Context context)
{
// 獲取程式預設的異常處理
mUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
// 把自定義的異常處理替換預設的
Thread.setDefaultUncaughtExceptionHandler(this);
mContext = context;
}
@Override
public void uncaughtException(Thread thread, Throwable ex)
{
//獲取異常寫入檔案
handleException(ex);
//先判斷是否連結了網路,開啟後臺服務,將異常檔案上傳到伺服器
if(NetWorkState.IsConnectNet(mContext))
{
Intent it = new Intent(mContext, ExceptionService.class);
mContext.startService(it);
}
//如果系統提供了預設到異常處理,則交給系統去結束程式,否則自己結束
if(mUncaughtExceptionHandler != null)
{
mUncaughtExceptionHandler.uncaughtException(thread, ex);
}else{
Process.killProcess(Process.myPid());
}
}
private boolean handleException(Throwable ex)
{
String xml = getExceptionXML(mContext, ex);
if(xml != null)
{
//儲存crash日誌檔案到sdcard
String filename = SaveFile(xml.getBytes());
if(filename != null)
{
return true;
}
}
return false;
}
public static String getExceptionXML(Context context, Throwable ex)
{
String xml = null;
if(context != null && ex != null)
{
xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><info>";
xml += collectDeviceInfo(context);//收集裝置資訊
xml += collectErrorInfo(ex); //收集錯誤資訊
xml += "</info>";
}
return xml;
}
}
複製程式碼
這裡首先要獲取得到crash資訊,然後將crash資訊存到sdcard,得到crash資訊檔案後,開啟後臺服務,將檔案上傳到後臺即可。這裡收集到資訊包括:應用版本號、手機配置資訊和crash資訊。
public class ExceptionService extends Service {
private boolean mIsRun;
private Handler mHandler = new Handler();
@Override
public void onCreate()
{
super.onCreate();
mIsRun = false;
}
@Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
if(intent != null && !mIsRun)
{
mIsRun = true;
StartUpload();
}
return super.onStartCommand(intent, flags, startId);
}
private void StartUpload()
{
new Thread(new Runnable()
{
@Override
public void run()
{
//這裡將crash檔案上傳到伺服器
//上傳檔案完畢之後,關閉後臺服務
mHandler.post(new Runnable() {
@Override
public void run() {
ExceptionService.this.stopSelf();
System.exit(0);
}
});
}
}).start();
}
}
複製程式碼
這個後臺服務主要的工作就是將crash上傳到伺服器,上傳完成就關閉服務。
public class BaseApplication extends Application {
private static Context mContext;
private CrashHandler mCrashHandler;
@Override
public void onCreate() {
mContext = this;
mCrashHandler = new CrashHandler();
mCrashHandler.init(mContext);
super.onCreate();
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
}
/**
* 獲取上下文
*
* @return
*/
public static Context getContext() {
return mContext;
}
public static BaseApplication getInstance() {
return (BaseApplication) mContext;
}
}
複製程式碼
這裡需要在onCreate方法裡面初始化CrashHandler,主要是為應用設定異常處理,然後程式才能獲取未處理的異常。
經過上面的步驟就可以處理crash了,只要應用crash了就會將資訊上傳到伺服器,我們從伺服器中獲取資訊,分析crash進而處理這些bug。