異常捕捉有助於我們調試錯誤,但是app發佈了自己看不到log怎麼辦?這時我們就需要AppException異常收集器了
異常的處理主要是實現UncaughtExceptionHandler這個接口,並重載uncaughtException方法,通過Throwable來獲取異常的信息。不明白UncaughtExceptionHandler的可以百度查查
AppException
package com.example.test;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import org.json.JSONObject;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.telephony.TelephonyManager;
public class AppException implements UncaughtExceptionHandler {
/** 程序的Context對象 ,傳入ApplicationContext */
private Context context;
private DeviceInfo devInfo;
/** 系統默認的UncaughtException處理類 */
private Thread.UncaughtExceptionHandler mDefaultHandler;
/** CrashHandler實例 */
private static AppException appException;
/** 保證只有一個CrashHandler實例 */
private AppException() {
}
/** 獲取CrashHandler實例 ,單例模式 */
public static AppException getInstance() {
if (appException == null) {
appException = new AppException();
}
return appException;
}
/**
* 初始化,註冊Context對象, 獲取系統默認的UncaughtException處理器, 設置該CrashHandler爲程序的默認處理器
*
* @param context
*/
public void init(Context context) {
this.context = context;
devInfo=collectDeviceInfo();
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* 當UncaughtException發生時會轉入該函數來處理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
handleException(ex);
if (mDefaultHandler != null) {
// 如果用戶沒有處理則讓系統默認的異常處理器來處理
mDefaultHandler.uncaughtException(thread, ex);
}
}
/**
* 自定義錯誤處理,收集錯誤信息 發送錯誤報告等操作均在此完成. 開發者可以根據自己的情況來自定義異常處理邏輯
*/
public String handleException(Throwable e) {
StringBuffer sb = new StringBuffer();
// 獲取classname、報錯的哪一行等
// String className = stacks[0].getFileName();
// String methodName = stacks[0].getMethodName();
// int lineNumber = stacks[0].getLineNumber();
// System.out.println("ElementException:"+"className:"+className+" methodName:"+methodName+" lineNumber:"+lineNumber);
// 獲取具體的報錯信息
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
// System.out.println("crashMessage:" + sw.toString());
// 直接定位報錯信息
// System.out.println("getCause:" + e.getMessage().toString());
sb.append("sdkVersion:"+devInfo.getOsVersion()+"\n")
.append("versionName:"+devInfo.getVersionName()+"\n")
.append("versionCode:"+devInfo.getVersionCode()+"\n")
.append("manufacturer:"+devInfo.getManufacturer()+"\n")
.append("model:"+devInfo.getModel()+"\n")
.append("deviceId:"+devInfo.getDeviceId()+"\n")
.append("Exception:"+sw.toString());
System.out.println("crashMessage:" + sb.toString());
return sb.toString();
}
/**
* 手機設備信息
*/
public DeviceInfo collectDeviceInfo() {
// TODO Auto-generated method stub
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_ACTIVITIES);
if (pi != null) {
DeviceInfo devInfo=new DeviceInfo();
// devInfo.setOsVersion(android.os.Build.VERSION.SDK);
devInfo.setOsVersion(android.os.Build.VERSION.RELEASE);
String versionName = pi.versionName == null ? "null": pi.versionName;
String versionCode = pi.versionCode + "";
devInfo.setVersionName(versionName);
devInfo.setVersionCode(versionCode);
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
StringBuilder sb = new StringBuilder();
devInfo.setDeviceId(tm.getDeviceId());
// 獲取手機型號
devInfo.setModel(android.os.Build.MODEL);
//獲取手機廠商:
devInfo.setManufacturer(android.os.Build.MANUFACTURER);
System.out.println("devInfo:"+devInfo);
return devInfo;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 獲取手機的硬件信息
*
* @return
*/
public String getMobileInfo() {
JSONObject json = new JSONObject();
// 通過反射獲取系統的硬件信息
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
json.put(field.getName(), field.get(null).toString());
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("getMobileInfo:"+json.toString());
return json.toString();
}
public class DeviceInfo{
private String osVersion;
private String versionName;
private String versionCode;
private String deviceId;
private String model;
private String manufacturer;
public String getOsVersion() {
return osVersion;
}
public void setOsVersion(String osVersion) {
this.osVersion = osVersion;
}
public String getVersionName() {
return versionName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
public String getVersionCode() {
return versionCode;
}
public void setVersionCode(String versionCode) {
this.versionCode = versionCode;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
@Override
public String toString() {
return "DeviceInfo [osVersion=" + osVersion + ", versionName="
+ versionName + ", versionCode=" + versionCode
+ ", deviceId=" + deviceId + ", model=" + model
+ ", manufacturer=" + manufacturer + "]";
}
}
}
獲取設備信息還需要權限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
使用的時候我們只要傳入ApplicationContext
AppException.getInstance().init(getApplicationContext());