Android 全域性異常捕獲
阿新 • • 發佈:2019-02-05
全域性異常捕獲
廢話不多說,直接上程式碼
package com.util;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import android.content.Context;
/**
* 全域性異常捕獲控制代碼類
*/
public class CrashHandler implements UncaughtExceptionHandler {
public static final String TAG = "CrashHandler";
public static final boolean DEBUG = false; // 是否開啟日誌輸出,在Debug狀態下開啟,
// 在Release狀態下關閉以提高程式效能
private static CrashHandler crashHandler;
private Thread.UncaughtExceptionHandler exceptionHandler; // 系統預設的UncaughtExceptionHandler
private Context context;
/**
* 私有建構函式
*/
private CrashHandler() {
}
/**
* @return 單例
*/
public static CrashHandler getInstance() {
if (crashHandler == null) {
crashHandler = new CrashHandler();
}
return crashHandler;
}
/**
* @param context
* 上下文物件
*/
public void init(Context context) {
this.context = context;
exceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); // 獲取系統預設的UncaughtExceptionHandler
Thread.setDefaultUncaughtExceptionHandler(this); // 設定本類物件crashHandler為程式的預設處理器
}
/**
* 當異常發生時,捕獲異常
*
* @param thread
* 執行緒
* @param ex
* 異常
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(thread, ex) && exceptionHandler != null) {
exceptionHandler.uncaughtException(thread, ex); // 如果使用者沒有處理則讓系統預設的異常處理器來處理
} else {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
SLog.Console("===============CrashHandler================");
SLog.saveException(e);
SLog.Console("==============CrashHandlerEnd==============");
}
}
}
/**
* 自定義異常處理
*
* @param ex
* 異常
* @return boolean 是否處理
*/
private boolean handleException(Thread thread, Throwable ex) {
if (ex == null) {
return true;
}
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
ex.printStackTrace(pw);
pw.flush();
sw.flush();
this.saveInfo2File(ex); // 儲存錯誤報告檔案
return true;
}
/**
* 儲存異常資訊到檔案中
*
* @param ex
* 異常
* @return String 異常資訊
*/
public String saveInfo2File(final Throwable ex) {
// if (MainApplication.getInstance().isTest) {
// new Thread(){
// @Override
// public void run() {
// Looper.prepare();
// String errorMsg=MessageUtils.getExcptionToastMessage(ex);
// Toast.makeText(MainApplication.getInstance(), "很抱歉,程式出現"+errorMsg+",即將退出.",
// Toast.LENGTH_LONG).show();
// Looper.loop();
// }
// }.start();
// }
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
String info = writer.toString();
printWriter.close();
FileUtil.saveLog("=================CrashInfo===============");
FileUtil.saveLog(info);
SLog.Console(info);
FileUtil.saveLog("================CrashInfoEnd=============");
return info;
}
}
然後在MainApplication中新增對應的宣告即可
package com.example.zxingdemo;
import android.app.Application;
import com.util.CrashHandler;
import com.util.PathUtil;
import com.util.SLog;
public class MainApplication extends Application {
private static MainApplication mApplication;
@Override
public void onCreate() {
super.onCreate();
mApplication = this;
PathUtil.getInstance().init(mApplication);
SLog.cleanOutOfDateLog();
// 新增全域性異常捕獲
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(getApplicationContext());
}
public static synchronized MainApplication getInstance() {
return mApplication;
}
}
最後一定要注意在Manifest裡邊指定Application
<application
android:name="com.example.zxingdemo.MainApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.karics.library.zxing.android.CaptureActivity"
android:theme="@android:style/Theme.NoTitleBar"
android:screenOrientation="portrait" >
</activity>
</application>