引言:Crash崩溃在Android程序开发中总是会遇见的,在本地调试的还好我没通常可以通过logcat日志打印来分析输出的日志 定位到问题。但是上了线各种复杂的环境就没那么好处理。这时候通常我会集成像Bugly这种sdk来分析问题。但是Bugly又是怎么做到crash的采集呢?
Crash分类:
-
Java层崩溃Crash:
Java层的崩溃一般比较好捕捉 java中的Thread提供了异常处理接口 Thread.UncaughtExceptionHandler
public class CrashHanler implements Thread.UncaughtExceptionHandler{
private static Thread.UncaughtExceptionHandler mDefaultExceptionHandler;
private static Context mContext;
public static void init(Context context){
mContext = context;
//获取默认ExceptionHandler
mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
//设置程序开发者的自行异常处理器 发生异常会回调到 uncaughtException
Thread.setDefaultUncaughtExceptionHandler(new CrashHanler());
}
@Override
public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
//异常回调处理方法
File crashFileDir = new File(mContext.getExternalFilesDir("crashReport"),"crash_info");
if(!crashFileDir.exists())
crashFileDir.mkdirs();
long time = System.currentTimeMillis();
String dateTimeStr = DateFormat.format("yyyy年MM月dd日 HH时mm分ss秒",time).toString();
String dateTimeFileStr = DateFormat.format("yyyyMMssHHmmss",time).toString();
File crashFile = new File(crashFileDir,dateTimeFileStr+".log");
//使用打印流打印到文件分
try {
PrintWriter pw = new PrintWriter(crashFile);
pw.println("crash发生线程:"+ thread.getName());
pw.println("时间:"+dateTimeStr);
pw.println("设备与APP版本信息:"+getDevicePhoneInfo());
pw.println("错误堆栈:");
throwable.printStackTrace(pw);
pw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}finally {
if(mDefaultExceptionHandler!=null)
mDefaultExceptionHandler.uncaughtException(thread,throwable);
}
}
private static String getDevicePhoneInfo() throws PackageManager.NameNotFoundException {...}
}
捕获记录文件.png
-
Native层崩溃Crash:
集成 google 的 breakpad 框架
JNI部分,先写native方法
public static native void initNativeCrash(String path);
native实现
#include <jni.h>
#include <android/log.h>
#include "breakpad/src/client/linux/handler/exception_handler.h"
#include "breakpad/src/client/linux/handler/minidump_descriptor.h"
extern "C"
JNIEXPORT void JNICALL
Java_com_chenx_crashreportproject_CrashReportManager_testNativeCrash(JNIEnv *env, jclass clazz) {
__android_log_print(ANDROID_LOG_INFO,"testNative","xxxxxxx test NDK Native crash. xxxxxxxx");
int *p = NULL;
*p = 10;
}
bool DumpCallback(const google_breakpad::MinidumpDescriptor &descriptor,
void* context,
bool succeeded){
__android_log_print(ANDROID_LOG_ERROR,"native","native crash:%s",descriptor.path());
return false;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_chenx_crashreportproject_CrashReportManager_initNativeCrash(JNIEnv *env,jclass clazz,jstring filepath){
const char* path = env->GetStringUTFChars(filepath,0);
__android_log_print(ANDROID_LOG_INFO, "native", "===> %s", path);
google_breakpad::MinidumpDescriptor descriptor(path);
static google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback,
NULL, true, -1);
env->ReleaseStringUTFChars(filepath,path);
}
1.通过linux的信号分发机制我们设置我们自己异常处理器就可以捕抓到native层的错误 但是文件我们是打不开的。这个时候如果是window系统 我们可以用minidump工具来转文件 minidump位于:AndroidStudio 安装目录下的\bin\lldb\bin
minidump目录.png2.然后通过cmd运行命令
minidump_stackwalk C:\Users\86136\Desktop\b47fc729-680c-4a62-7fd8b3ad-9ad095d9.dmp >myCrash.txt
这样就可以得到我们可读的crash文件
网友评论