异常捕捉有助于我们调试错误,但是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());