最近遇到一个问题,app遇到异常就崩溃了,断点也打不到,日志也被刷掉了,看不到异常消息处理不了异常,没有集成第三方工具。
想了做个全局异常类CrashHandler,处理全局异常:
此类不能与google的firebase 、crashlytics一块使用,
使用方法在MyApplication的onCreate中初始化一下,就ok
public class MyApplication extends Application {
private static final String TAG = "MyApplication";
@Override
public void onCreate() {
super.onCreate();
/**全局异常捕捉*/
CrashHandler.getInstance().init(this);
}
}
/**
* 全局异常捕捉,日志文件保存在android/data/app报名/cache目录中
*/
public class CrashHandler implements UncaughtExceptionHandler {
/**
* TAG
*/
private static final String TAG = "CrashHandler";
/**
* uploadUrl 服务器的地址,根据自己的情况进行更改
*/
private static final String uploadUrl = "http://3.saymagic.sinaapp.com/ReceiveCrash.php";
/**
* localFileUrl 本地log文件的存放地址
*/
private static String localFileUrl = "";
/**
* instance
*/
private volatile static CrashHandler instance;
/**
* mDefaultHandler
*/
private UncaughtExceptionHandler defaultHandler;
/**
* infos
*/
private Map<String, String> infos = new HashMap<>();
/**
* formatter
*/
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* context
*/
private Context context;
private CrashHandler() {
}
public static CrashHandler getInstance() {
if (instance == null) {
synchronized (CrashHandler.class) {
if (instance == null) {
instance = new CrashHandler();
}
}
}
return instance;
}
/**
* @param ctx 初始化,此处最好在Application的OnCreate方法里来进行调用
*/
public void init(Context ctx) {
this.context = ctx;
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* uncaughtException 在这里处理为捕获的Exception
*/
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
if(!handleException(throwable)) {
if (defaultHandler != null) {
defaultHandler.uncaughtException(thread, throwable);
}
}
// 退出程序
android.os.Process.killProcess(android.os.Process.myPid());
}
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
Log.d("TAG", "收到崩溃");
collectDeviceInfo(context);
writeCrashInfoToFile(ex);
return true;
}
/**
* @param ctx 手机设备相关信息
*/
public void collectDeviceInfo(Context ctx) {
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);
infos.put("crashTime", formatter.format(new Date()));
}
} catch (NameNotFoundException e) {
}
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
infos.put(field.getName(), field.get(null).toString());
Log.d(TAG, field.getName() + " : " + field.get(null));
} catch (Exception e) {
}
}
}
/**
* @param ex 将崩溃写入文件系统
*/
private void writeCrashInfoToFile(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);
//上传到umeng
//MobclickAgent.reportError(context, sb.toString());
//这里把刚才异常堆栈信息写入SD卡的Log日志里面
String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/crash/";
localFileUrl = writeLog(sb.toString(), filePath);
}
/**
* @param log
* @param name
* @return 返回写入的文件路径 写入Log信息的方法,写入到SD卡里面
*/
private String writeLog(String log, String name) {
SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sDateFormat.format(new Date());
String filename = name + "crash" + date + ".log";
File file = new File(filename);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try {
file.createNewFile();
FileWriter fw = new FileWriter(file, true);
BufferedWriter bw = new BufferedWriter(fw);
//写入相关Log到文件
bw.write(log);
bw.newLine();
bw.close();
fw.close();
return filename;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private void restart() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
} finally {
Context appContext = context.getApplicationContext();
Intent intent = appContext.getPackageManager().getLaunchIntentForPackage(appContext.getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent restartIntent = PendingIntent.getActivity(appContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);
System.exit(0);
}
}
}