源碼下載“:http://www.eoeandroid.com/thread-587310-1-1.html
當我們的應用在出現bug並強制退出的時候,我們可能不捕捉不了相關的異常,不過,我們可以設置自定義的異常來捕捉全局異常
1.捕捉全局異常的類
-
package com.happy.application;
-
-
import java.io.File;
-
import java.io.FileOutputStream;
-
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.app.Application;
-
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.Looper;
-
import android.widget.Toast;
-
-
import com.happy.common.Constants;
-
import com.happy.logger.LoggerManage;
-
-
public class CrashApplication extends Application {
-
-
@Override
-
public void onCreate() {
-
super.onCreate();
-
CrashHandler catchHandler = new CrashHandler();
-
catchHandler.init(getApplicationContext());
-
}
-
-
/**
-
* UncaughtException處理類,當程序發生Uncaught異常的時候,有該類來接管程序,並記錄錯誤報告.
-
*
-
* 需要在Application中註冊,爲了要在程序啓動器就監控整個程序。
-
*/
-
public class CrashHandler implements UncaughtExceptionHandler {
-
-
private LoggerManage logger;
-
private SimpleDateFormat crashfile = new SimpleDateFormat("yyyy-MM-dd");// 日誌文件格式
-
-
// 系統默認的UncaughtException處理類
-
private Thread.UncaughtExceptionHandler mDefaultHandler;
-
// 程序的Context對象
-
private Context mContext;
-
// 用來存儲設備信息和異常信息
-
private Map<String, String> infos = new HashMap<String, String>();
-
-
/** 保證只有一個CrashHandler實例 */
-
private CrashHandler() {
-
}
-
-
/**
-
* 初始化
-
*/
-
public void init(Context context) {
-
mContext = context;
-
logger = LoggerManage.getZhangLogger(mContext);
-
// 獲取系統默認的UncaughtException處理器
-
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
-
// 設置該CrashHandler爲程序的默認處理器
-
Thread.setDefaultUncaughtExceptionHandler(this);
-
}
-
-
/**
-
* 當UncaughtException發生時會轉入該函數來處理
-
*/
-
@Override
-
public void uncaughtException(Thread thread, Throwable ex) {
-
if (!handleException(ex) && mDefaultHandler != null) {
-
// 如果用戶沒有處理則讓系統默認的異常處理器來處理
-
mDefaultHandler.uncaughtException(thread, ex);
-
} else {
-
try {
-
Thread.sleep(1000);
-
} catch (InterruptedException e) {
-
logger.e(e.toString());
-
}
-
// 退出程序
-
android.os.Process.killProcess(android.os.Process.myPid());
-
System.exit(1);
-
}
-
}
-
-
/**
-
* 自定義錯誤處理,收集錯誤信息 發送錯誤報告等操作均在此完成.
-
*
-
* @param ex
-
* [url=home.php?mod=space&uid=7300]@return[/url] true:如果處理了該異常信息;否則返回false.
-
*/
-
private boolean handleException(Throwable ex) {
-
if (ex == null) {
-
return false;
-
}
-
// 收集設備參數信息
-
collectDeviceInfo(mContext);
-
// 使用Toast來顯示異常信息
-
new Thread() {
-
@Override
-
public void run() {
-
Looper.prepare();
-
Toast.makeText(mContext, "程序出現異常,即將退出", Toast.LENGTH_SHORT)
-
.show();
-
Looper.loop();
-
}
-
}.start();
-
// 保存日誌文件
-
saveCatchInfoFile(ex);
-
return true;
-
}
-
-
/**
-
* 收集設備參數信息
-
*
-
* @param mContext
-
*/
-
private void collectDeviceInfo(Context ctx) {
-
// 獲取當前程序的版本號. 版本的id
-
try {
-
PackageManager pm = ctx.getPackageManager();
-
PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
-
PackageManager.GET_ACTIVITIES);
-
if (pi != null) {
-
String versionName = pi.versionName == null ? "null"
-
: pi.versionName;
-
String versionCode = pi.versionCode + "";
-
infos.put("versionName", versionName);
-
infos.put("versionCode", versionCode);
-
}
-
} catch (NameNotFoundException e) {
-
logger.e(e.toString());
-
}
-
// 獲取手機的硬件信息
-
// 通過反射獲取系統的硬件信息
-
Field[] fields = Build.class.getDeclaredFields();
-
for (Field field : fields) {
-
try {
-
field.setAccessible(true);
-
infos.put(field.getName(), field.get(null).toString());
-
} catch (Exception e) {
-
logger.e(e.toString());
-
}
-
}
-
}
-
-
/**
-
* 保存日誌文件
-
*
-
* @param ex
-
*/
-
private void saveCatchInfoFile(Throwable ex) {
-
-
StringBuffer sb = new StringBuffer();
-
for (Map.Entry<String, String> entry : infos.entrySet()) {
-
String key = entry.getKey();
-
String value = entry.getValue();
-
sb.append(key + "=" + value + "\n");
-
}
-
-
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();
-
}
-
printWriter.close();
-
String result = writer.toString();
-
sb.append(result);
-
try {
-
// 用於格式化日期,作爲日誌文件名的一部分
-
String time = crashfile.format(new Date());
-
String fileName = time + ".log";
-
String path = Constants.PATH_CRASH + File.separator;
-
File dir = new File(path);
-
if (!dir.exists()) {
-
dir.mkdirs();
-
}
-
FileOutputStream fos = new FileOutputStream(path + fileName);
-
fos.write(sb.toString().getBytes());
-
fos.close();
-
} catch (Exception e) {
-
logger.e(e.toString());
-
}
-
}
-
}
-
}
<application
android:name="com.happy.application.CrashApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
3.調用
-
package com.happy.ui;
-
-
import com.happy.logger.LoggerManage;
-
-
import android.os.Bundle;
-
import android.app.Activity;
-
import android.view.Menu;
-
-
public class MainActivity extends Activity {
-
-
private LoggerManage logger;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
init();
-
}
-
-
private void init() {
-
// logger = LoggerManage.getZhangLogger(this);
-
logger.i("測試");
-
}
-
-
// @Override
-
// public boolean onCreateOptionsMenu(Menu menu) {
-
// getMenuInflater().inflate(R.menu.main, menu);
-
// return true;
-
// }
-
-
}