奔溃捕获

作者: lipyhui | 来源:发表于2018-10-18 16:11 被阅读0次

一、说明

  笔记主要是记录一些本人在开发当中的学习和使用笔记。笔记内容包含一些本人觉得重要的知识点、本人易犯的错误等。
  由于本人水平有限,其中出现的错误或者不合理的地方望各位读者多多包含,并指出其中不合理和错误的地方,以便我来修正。谢谢!

二、笔记时间

  2018年10月17日

三、简述

  本文主要讲述Android APP为什么需要奔溃捕获和奔溃捕获的方式。

四、详情

1、简介

  在开发Android APP当中,难免会有一些无法预期的错误,或者在特殊环境下和操作下才会出现的错误。当这些错误发生时,会导致APP奔溃并且出现不友好的界面,影响APP的体验。
  那么我们程序员GG怎么解决这些错误,还给用户一个体验完美的APP呢?这个时候奔溃捕获的作用就体现出来了,我们通过奔溃捕获获取奔溃日志,并把奔溃日志保存到本地或者发送到日志服务器,以便程序员GG来查看和解决错误。

2、奔溃捕获示例

2.1、实现UncaughtExceptionHandler

//CrashHandler.java
package com.lipy.demo.crashhandler;

import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;

/**
 * 创建人: lipy
 * 创建时间: 2017/8/4
 * 修改人:lipy
 * 修改时间:2017/8/4
 * 修改内容:
 *
 * 功能描述:捕获奔溃并重启
 */
public class CrashHandler implements Thread.UncaughtExceptionHandler {
    private final String PATH = "/storage/sdcard0/crash_logger.txt";

    public static CrashHandler mAppCrashHandler;

    private Thread.UncaughtExceptionHandler mDefaultHandler;

    private Application mAppContext;

    public static CrashHandler getInstance() {
        if (mAppCrashHandler == null) {
            mAppCrashHandler = new CrashHandler();
        }
        return mAppCrashHandler;
    }

    public void initCrashHandler(Application application) {
        this.mAppContext = application;
        // 获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            // 如果用户没有处理则让系统默认的异常处理器来处理
            //mDefaultHandler.uncaughtException(thread, ex);
        }

        //设置重启定时器
        AlarmManager mgr = (AlarmManager) mAppContext.getSystemService(Context.ALARM_SERVICE);

        //1秒后重启
        Intent intent = new Intent(mAppContext, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent restartIntent = PendingIntent.getActivity(mAppContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用

        //杀死进程
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(0);
        System.gc();
    }

    /**
     * 错误处理,收集错误信息、发送错误报告等操作均在此完成.
     *
     * @param ex 错误信息
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }

        //收集奔溃日志
        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();

        //保存日志
        saveInfo(result);

        // 自定义处理错误信息
        return true;
    }

    /**
     * 保存错误信息到本地文件
     *
     * @param msg String
     */
    private void saveInfo(String msg) {
        try {
            String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis());
            String info = time + ":\n\r" + msg + "\n\r\n\r";
            RandomAccessFile log = new RandomAccessFile(PATH, "rw");
            log.skipBytes((int) log.length());
            log.write(info.getBytes());
            log.close();
        } catch (Exception e) {
            Log.e("CrashHandler", "save crash info err !!" + e.toString());
        }
    }
}

2.2、自定义Application

//MyApplication.java
package com.lipy.demo.crashhandler;

import android.app.Application;

/**
 * 创建人: lipy
 * 创建时间: 2018/10/18
 * 修改人:lipy
 * 修改时间:2018/10/18
 * 修改内容:
 *
 * 功能描述:自定义Application
 */
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        //异常捕获初始化
        CrashHandler.getInstance().initCrashHandler(this); // 一定要初始化
    }
}

2.3、注册清单

  在AndroidManifest.xml中注册MyApplication,通过android:name=".MyApplication" 使APP的Application使用自定义的MyApplication。

<application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round">

</application>

  由于中示例的MyApplication中的奔溃日志是保存到本地文件当中,因此需要添加文件读写权限。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

2.4、示例源码

  示例源码:https://github.com/lipyhui/android_app_demo/tree/master/CrashHandler

相关文章

  • iOS-千奇百怪的奔溃

    App 上线后,我们最怕的应该就是异常奔溃了。常见的奔溃类型分两种:信号可捕获奔溃、信号不可捕获奔溃,前者比较典型...

  • 奔溃捕获

    一、说明   笔记主要是记录一些本人在开发当中的学习和使用笔记。笔记内容包含一些本人觉得重要的知识点、本人易犯的错...

  • Android应用异常奔溃捕获

    应用发布上线后,难免会有bug导致应用奔溃异常退出,FC等现象,及时获取错误信息,定位bug位置,成了首要问题。

  • 异常捕获ios实现

    2016年12月6日一.效果图(奔溃后第二次启动后的打开隐藏功能显示奔溃信息) 二.实现1.注册异常捕获机制(程序...

  • 关于符号化(symbolic)和奔溃信息的分析

    最初始的需求是:怎么定位线上的奔溃。 那就是捕获NSException,收集发送到后台统一处理。或者接入第三方奔溃...

  • iOS崩溃分析及全面监控

    奔溃信息分类 可以通过信号捕获的崩溃信息:数组越界,野指针问题,NSNotification线程问题,KVO 问题...

  • DYLD, Library not loaded: /usr/l

    奔溃日志 奔溃表现:iOS12.1 及以下启动奔溃奔溃日志: 解决方法:关闭bitcode,重新打包上传appst...

  • 奔溃

    送表弟们去上学的路上,听说刚才忘了拿《斗罗大陆》,却又接着说可以向同学借。我的内心立即奔溃了,满满的无力感! 当初...

  • 奔溃

    我总是想不让自己在乎别人的眼光,所以我总是在街上很自在,不担心自己的丑态被别人看到,我也经常对女友这么说,不要在意...

  • 奔溃

    工作到奔溃 加班到晚上八九点 没有人会理解你的苦楚,下班回家星空相伴,人与人之间的关系脆弱到分崩离析,工作后发现身...

网友评论

    本文标题:奔溃捕获

    本文链接:https://www.haomeiwen.com/subject/wmzlzftx.html