崩溃处理,ACRA核心流程简析

崩溃处理,ACRA核心流程简析_第1张图片
ACRA

2016/10/02
上海
Read the fucking source code。

    ACRA Application Crash Reports for Android 。
    GitHub:https://github.com/ACRA

(文章基于ACRA v4.8.0)
ACRA目的简单明了,收集App崩溃堆栈信息,生成报告并发送到指定端。

通俗的崩溃处理流程:
1,实现Thread.UncaughtExceptionHandler接口,自定义崩溃处理器。
2,保留系统默认Thread.UncaughtExceptionHandler接口(通过Thread.getDefaultUncaughtExceptionHandler()获得),
   当自定义处理器无法分析崩溃异常时,提交给默认处理器解决。
3,绑定自定义处理器(通过Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler)方法)
4,崩溃,自定义处理器捕捉崩溃异常,生成报表。
5,处理报表(我习惯发送到静态BroadcastReceiver处理报表并重启应用,尝试将报表发送到服务器,若发送失败,则写入本地文件)
ACRA核心类:
ACRA    ACRA入口类
ACRAConfiguration    ACRA配置器
ConfiguraitonBuilder    配置器的构造器
ErrorReporter    崩溃堆栈捕捉线程(实现Thread.UncaughtExceptionHandler)
ReportBuilder    错误报表生成器
SendService    报表提交服务(处于ErrorReporter与ReportSender之间)
SenderServiceStarter    SendService帮助类
ReportSender    错误报表发送器
ReportSenderFactory    ReportSender工厂类

ACRA初始化:

//初始化三种方式
ACRA.init(Application app);
ACRA.init(Application app, ACRAConfiguration config);
//ACRAConfiguration是ACRA配置器,与注解是相同功能,ACRAConfiguration优先于注解
//checkReportsOnApplicationStart,这个参数决定了三件事:
  1,是否删除上个版本未发送的错误报告,
  2,是否删除用户未批准发送的错误报告,
  3,是否尝试发送之前发送失败的错误报表。
ACRA.init(Application app, ACRAConfiguration config, boolean checkReportsOnApplicationStart);
//省略版本适配,优化等代码
public static void init(Application app, ACRAConfiguration config, boolean checkReportsOnApplicationStart){
    //判断ACRA是否处于运行状态
    final boolean senderServiceProcess = isACRASenderServiceProcess(app);
    //android 系统版本是否>=8
    boolean supportedAndroidVersion = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO);

    mApplication = app;
    configProxy = config;
    try {
    ...
        省略ACRA版本适配相关,ACRA版本升级,本地错误报表转移
    ...

        //checkCrashResources()方法检查注释中的相关字段是否完整,Toast模式必须设置ToastText字段等..
        config.checkCrashResources();
        //是否加载Acra
        final boolean enableAcra = supportedAndroidVersion && !shouldDisableACRA(prefs);
        //创建ErrorReporter实例
        errorReporterSingleton = new ErrorReporter(mApplication, configProxy, prefs, enableAcra, supportedAndroidVersion, !senderServiceProcess);
        //
        if (checkReportsOnApplicationStart && !senderServiceProcess) {
            //ApplicationStartupProcessor 用于每次ACRA初始化时,查找任何现有的报告并发送。
            final ApplicationStartupProcessor startupProcessor = new ApplicationStartupProcessor(mApplication,  config);
            //如果配置器中设定删除App上个版本未发送的错误报表
            if (config.deleteOldUnsentReportsOnApplicationStart()) {
                //则删除
                startupProcessor.deleteUnsentReportsFromOldAppVersion();
            }
            //如果配置器中设定删除用户未批准发送的错误报告
            if (config.deleteUnapprovedReportsOnApplicationStart()) {
                //则删除
                startupProcessor.deleteAllUnapprovedReportsBarOne();
            }
            //如果可以启动ACRA
            if (enableAcra) {
              //尝试发送之前发送失败的错误报表。                
              startupProcessor.sendApprovedReports();
            }
        }
    } catch (ACRAConfigurationException e) {
        log.w(LOG_TAG, "Error : ", e);
    }
    .......
}

ErrorReporter,崩溃堆栈捕捉线程

public class ErrorReporter implements Thread.UncaughtExceptionHandler

ErrorReporter初始化:

//省略版本适配,优化等代码
ErrorReporter(Application context, ACRAConfig config, SharedPreferences prefs, boolean enabled, boolean supportedAndroidVersion, boolean listenForUncaughtExceptions) {
    this.context = context;
    this.config = config;
    this.supportedAndroidVersion = supportedAndroidVersion;
    
......
    //获取系统默认异常捕捉线程
    defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
    //将ErrorReporter设置为默认异常捕捉线程
    Thread.setDefaultUncaughtExceptionHandler(this);

......
}

ErrorReporter异常处理:

@Overridepublic void uncaughtException(Thread t, Throwable e) {
    ......
        //出现异常,利用错误报表构造器,生成错误报表
        new ReportBuilder()
             //ReportBuilder内部持有崩溃数据t实例
            .uncaughtExceptionThread(t)
            //ReportBuilder内部持有崩溃数据e实例
            .exception(e)
            //ReportBuilder内部有app是否结束的标示
            .endApplication()
            //构建
            .build(reportExecutor);
    ......
}
public void build(ReportExecutor reportExecutor) {
    .....
    //通过错误报表构造器,分析错误堆栈,并写入本地文件
    reportExecutor.execute(ReportBuilder.this);
}
public void execute(final ReportBuilder reportBuilder) {
    ...分析并写入本地,再根据配置,显示对应的提示...
    //发送错误报表
    startSendingReports(是否是静默发送, 是否直接批准发送);
}
private void startSendingReports(boolean onlySendSilentReports, boolean approveReportsFirst) {
......
        //创建SenderServiceStarter 对象
        final SenderServiceStarter starter = new SenderServiceStarter(context, config);
        //调用startService方法
        starter.startService(onlySendSilentReports, approveReportsFirst);
......
    } 
}
//启动SenderService服务
public void startService(boolean onlySendSilentReports, boolean approveReportsFirst) {
    final Intent intent = new Intent(context, SenderService.class);
    //存入是否静默发送
    intent.putExtra(SenderService.EXTRA_ONLY_SEND_SILENT_REPORTS, onlySendSilentReports);
    //存入是否直接批准发送
    intent.putExtra(SenderService.EXTRA_APPROVE_REPORTS_FIRST, approveReportsFirst);
    //存入发射器工厂类的Class对象,此对象为ReportSenderFactory实例
    intent.putExtra(SenderService.EXTRA_REPORT_SENDER_FACTORIES, config.reportSenderFactoryClasses());
    //存入ACRA配置器
    intent.putExtra(SenderService.EXTRA_ACRA_CONFIG, config);
    //启动SenderService
    context.startService(intent);
}

SenderService继承自IntentService

public class SenderService extends IntentService

ReportSenderFactory接口

public interface ReportSenderFactory {
     //返回ReportSender 实例
    ReportSender create(Context context, ACRAConfig config);
}

ReportSender 接口

public interface ReportSender {
    //处理错误报表
    void send(Context context, CrashReportData errorContent) throws ReportSenderException;
}
//启动IntentService,调用startService(intent);intent都会传入此方法
@Overrideprotected void onHandleIntent(final Intent intent) {
    //是否静默发送
    final boolean onlySendSilentReports = intent.getBooleanExtra(EXTRA_ONLY_SEND_SILENT_REPORTS, false);
    //是否直接批准发送
    final boolean approveReportsFirst = intent.getBooleanExtra(EXTRA_APPROVE_REPORTS_FIRST, false);
    //发射器工厂类
    final Class[] senderFactoryClasses =            (Class[]) intent.getSerializableExtra(EXTRA_REPORT_SENDER_FACTORIES);
    //ACRA配置器
    final ACRAConfig config = (ACRAConfig) intent.getSerializableExtra(EXTRA_ACRA_CONFIG);
    try {
        //配置器ReportSenderFactory可以配置多个,所以ReportSender实例的个数与ReportSenderFactory个数相同,getSenderInstances方法通过ReportSenderFactory.Class创建ReportSenderFactory实例,并创建ReportSender,返回ReportSender列表
        final List senderInstances = getSenderInstances(config, senderFactoryClasses);
        ......
        // 获取本地所有错误报表
        final File[] reports = locator.getApprovedReports();
        //ReportDistributor 用于向所有ReportSender实例分发报告
        final ReportDistributor reportDistributor = new ReportDistributor(this, config, senderInstances);
        for (final File report : reports) {
......
            //向所有ReportSender实例分发报告
            reportDistributor.distribute(report);
......
        }
    } catch (Exception e) {
        ......
    }
}
public void distribute(File reportFile) {
......
        sendCrashReport(reportFile格式化后);
......
}
//CrashReportData 为错误信息格式化后的对象
public void sendCrashReport(CrashReportData errorContent) {
......
  //遍历所有ReportSender 实例
  for (ReportSender sender : reportSenders) {
......
        //通过ReportSender 实例发送错误报告
        sender.send(context, errorContent);
......
  }
......
}

你可能感兴趣的:(崩溃处理,ACRA核心流程简析)