不管你多麼仔細,程式總是會出錯,下面方法是個全域的異常捕獲方法!希望對大家有協助!
1.用的時候,需要在applicaion裡面調用,代碼如下:
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(this);
2. 下面是主要的功能類:
package com.google.utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
/**
* UncaughtException處理類,當程式發生Uncaught異常的時候,由該類來接管程式,並記錄發送錯誤報表.
*/
public class CrashHandler implements UncaughtExceptionHandler {
private static final String TAG = "CrashHandler";
private Thread.UncaughtExceptionHandler mDefaultHandler;// 系統預設的UncaughtException處理類
private static CrashHandler INSTANCE = new CrashHandler();// CrashHandler執行個體
private Context mContext;// 程式的Context對象
private Map<String, String> info = new HashMap<String, String>();// 用來存放裝置資訊和異常資訊
private SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd-HH-mm-ss");// 用于格式化日期,作為記錄檔名的一部分
/** 保證只有一個CrashHandler執行個體 */
private CrashHandler() {}
/** 擷取CrashHandler執行個體 ,單例模式 */
public static CrashHandler getInstance() {
return INSTANCE;
}
//初始化
public void init(Context context) {
mContext = context;
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 擷取系統預設的UncaughtException處理器
Thread.setDefaultUncaughtExceptionHandler(this);// 設定該CrashHandler為程式的預設處理器
}
/**
* 當UncaughtException發生時會轉入該重寫的方法來處理
*/
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果自訂的沒有處理則讓系統預設的異常處理器來處理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
Thread.sleep(3000);// 如果處理了,讓程式繼續運行3秒再退出,保證檔案儲存並上傳到伺服器
} catch (InterruptedException e) {
e.printStackTrace();
}
// 退出程式
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
/**
* 自訂錯誤處理,收集錯誤資訊 發送錯誤報表等操作均在此完成.
* @param ex 異常資訊
× @ true 如果處理了該異常資訊;否則返回false.
*/
public boolean handleException(Throwable ex) {
Log.e("lixp", "ex ===========" + ex);
if (ex == null)
return false;
new Thread() {
public void run() {
Looper.prepare();
Toast.makeText(mContext, "異常退出。。。", 0).show();
Looper.loop();
}
}.start();
// 收集裝置參數資訊
collectDeviceInfo(mContext);
// 儲存記錄檔
saveCrashInfo2File(ex);
return true;
}
/**
* 收集裝置參數資訊
* @param context
*/
public void collectDeviceInfo(Context context) {
try {
PackageManager pm = context.getPackageManager();// 獲得包管理器
PackageInfo pi = pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_ACTIVITIES);// 得到該應用的資訊,即主Activity
if (pi != null) {
String versionName = pi.versionName == null ? "null"
: pi.versionName;
String versionCode = pi.versionCode + "";
info.put("versionName", versionName);
info.put("versionCode", versionCode);
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
// 反射機制
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
info.put(field.getName(), field.get("").toString());
Log.d(TAG, field.getName() + ":" + field.get(""));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
//用檔案儲存異常資訊
private String saveCrashInfo2File(Throwable ex) {
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, String> entry : info.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\r\n");
}
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
ex.printStackTrace(pw);
Throwable cause = ex.getCause();
// 迴圈著把所有的異常資訊寫入writer中
while (cause != null) {
cause.printStackTrace(pw);
cause = cause.getCause();
}
pw.close();// 記得關閉
String result = writer.toString();
sb.append(result);
// 儲存檔案
long timetamp = System.currentTimeMillis();
String time = format.format(new Date());
String fileName = "crash-" + time + "-" + timetamp + ".log";
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try {
File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Exception");
Log.d("CrashHandler", dir.toString());
if (!dir.exists())
dir.mkdir();
FileOutputStream fos = new FileOutputStream(new File(dir,
fileName));
fos.write(sb.toString().getBytes());
fos.close();
return fileName;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}