异常捕获

重启

CrashManagerInitConfigure

package widget.crash;

import android.app.Application;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.SystemClock;

import androidx.annotation.NonNull;

import com.zsp.utilone.intent.IntentUtils;
import com.zsp.utilone.log.ErrorLogManager;
import com.zsp.utilone.log.LogManager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import value.Folder;

/**
 * Created on 2018/5/24.
 *
 * @author 郑少鹏
 * @desc 崩溃管理器初始化配置
 */
public class CrashManagerInitConfigure implements Thread.UncaughtExceptionHandler {
    private static final String TAG = "CrashManager";
    /**
     * 实例
     */
    private static CrashManagerInitConfigure instance;
    /**
     * Application
     */
    private Application application;
    /**
     * 系统默UncaughtException处理类
     */
    private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
    /**
     * 存设备信息和异常信息
     */
    private Map<String, String> information = new HashMap<>();
    /**
     * 格式化日期(日志文件名部分)
     */
    private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.CHINA);

    /**
     * 仅一CrashHandler实例
     *
     * @param application Application
     */
    private CrashManagerInitConfigure(Application application) {
        this.application = application;
        uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * CrashHandler实例
     *
     * @param application Application
     */
    public static void getInstance(Application application) {
        CrashManagerInitConfigure crashManagerInitConfigure = instance;
        if (crashManagerInitConfigure == null) {
            synchronized (CrashManagerInitConfigure.class) {
                crashManagerInitConfigure = instance;
                if (crashManagerInitConfigure == null) {
                    crashManagerInitConfigure = new CrashManagerInitConfigure(application);
                    instance = crashManagerInitConfigure;
                }
            }
        }
    }

    /**
     * UncaughtException时转该函数处理
     *
     * @param thread    线程
     * @param throwable 异常
     */
    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
        LogManager.e(TAG, thread.getName(), throwable);
        if (!handleException(throwable) && uncaughtExceptionHandler != null) {
            // 程序没处理则系统默异常处理器处理
            uncaughtExceptionHandler.uncaughtException(thread, throwable);
        } else {
            SystemClock.sleep(500);
            // 重启
            IntentUtils.restart(application);
            // 杀已崩进程
            android.os.Process.killProcess(android.os.Process.myPid());
        }
    }

    /**
     * 自定错误处理
     * <p>
     * 收集错误信息、发送错误报告等均在此完成。
     *
     * @param throwable 异常
     * @return true处理异常,不再上抛;false不处理异常,存信息并交上层(系统异常处理器)处理
     */
    private boolean handleException(Throwable throwable) {
        if (throwable == null) {
            return false;
        }
        // 收集设备参数信息
        collectDeviceInfo(application);
        // 存错误信息至文件
        saveCrashInfoToFile(throwable);
        return true;
    }

    /**
     * 收设备参数信息
     *
     * @param application Application
     */
    private void collectDeviceInfo(Application application) {
        try {
            PackageManager pm = application.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(application.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                information.put("versionName", versionName);
                information.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
            ErrorLogManager.e(TAG, "an error occurred when collecting package info", e);
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                information.put(field.getName(), Objects.requireNonNull(field.get(null), "must not be null").toString());
            } catch (Exception e) {
                ErrorLogManager.e(TAG, "an error occurred when collecting crash info", e);
            }
        }
    }

    /**
     * 存错误信息至文件
     *
     * @param throwable 异常
     */
    private void saveCrashInfoToFile(Throwable throwable) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : information.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key).append("=").append(value).append("\n");
        }
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        throwable.printStackTrace(printWriter);
        Throwable cause = throwable.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
        try {
            String time = dateFormat.format(new Date());
            String fileName = "lll" + time + ".log";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                String path = Folder.CRASH;
                File dir = new File(path);
                if (!dir.exists() && dir.mkdirs()) {
                    FileOutputStream fos = new FileOutputStream(path + fileName);
                    fos.write(sb.toString().getBytes());
                    LogManager.eTag("saveCrashInfoToFile", sb.toString());
                    fos.close();
                } else {
                    FileOutputStream fos = new FileOutputStream(path + fileName);
                    fos.write(sb.toString().getBytes());
                    LogManager.eTag("saveCrashInfoToFile", sb.toString());
                    fos.close();
                }
            }
        } catch (Exception e) {
            ErrorLogManager.e(TAG, "An error occurred while writing to file.", e);
        }
    }
}

Application

CrashManagerInitConfigure.getInstance(this);

退出

package widget.crash;

import android.app.Application;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.SystemClock;

import androidx.annotation.NonNull;

import com.zsp.utilone.activity.ActivitySuperviseManager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;

import timber.log.Timber;
import value.Folder;

/**
 * Created on 2018/5/24.
 *
 * @author 郑少鹏
 * @desc 崩溃管理器初始化配置
 */
public class CrashManagerInitConfigure implements Thread.UncaughtExceptionHandler {
    /**
     * 实例
     */
    private static CrashManagerInitConfigure instance;
    /**
     * Application
     */
    private Application application;
    /**
     * 系统默UncaughtException处理类
     */
    private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
    /**
     * 存设备信息和异常信息
     */
    private Map<String, String> information = new HashMap<>();
    /**
     * 格式化日期(日志文件名部分)
     */
    private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.CHINA);

    /**
     * 仅一CrashHandler实例
     *
     * @param application Application
     */
    private CrashManagerInitConfigure(Application application) {
        this.application = application;
        uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * CrashHandler实例
     *
     * @param application Application
     */
    public static void getInstance(Application application) {
        CrashManagerInitConfigure crashManagerInitConfigure = instance;
        if (crashManagerInitConfigure == null) {
            synchronized (CrashManagerInitConfigure.class) {
                crashManagerInitConfigure = instance;
                if (crashManagerInitConfigure == null) {
                    crashManagerInitConfigure = new CrashManagerInitConfigure(application);
                    instance = crashManagerInitConfigure;
                }
            }
        }
    }

    /**
     * UncaughtException时转该函数处理
     *
     * @param thread    线程
     * @param throwable 异常
     */
    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
        Timber.e(throwable);
        if (!handleException(throwable) && uncaughtExceptionHandler != null) {
            // 程序没处理则系统默异常处理器处理
            uncaughtExceptionHandler.uncaughtException(thread, throwable);
        } else {
            SystemClock.sleep(200);
            // 退应用
            ActivitySuperviseManager.appExit();
            // 杀已崩进程
            android.os.Process.killProcess(android.os.Process.myPid());
        }
    }

    /**
     * 自定错误处理
     * <p>
     * 收集错误信息、发送错误报告等均在此完成。
     *
     * @param throwable 异常
     * @return true处理异常,不再上抛;false不处理异常,存信息并交上层(系统异常处理器)处理
     */
    private boolean handleException(Throwable throwable) {
        if (throwable == null) {
            return false;
        }
        // 收集设备参数信息
        collectDeviceInfo(application);
        // 存错误信息至文件
        saveCrashInfoToFile(throwable);
        return true;
    }

    /**
     * 收设备参数信息
     *
     * @param application Application
     */
    private void collectDeviceInfo(Application application) {
        try {
            PackageManager pm = application.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(application.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                information.put("versionName", versionName);
                information.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
            Timber.e(e, "an error occurred when collecting package info");
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                information.put(field.getName(), Objects.requireNonNull(field.get(null), "must not be null").toString());
            } catch (Exception e) {
                Timber.e(e, "an error occurred when collecting crash info");
            }
        }
    }

    /**
     * 存错误信息至文件
     *
     * @param throwable 异常
     */
    private void saveCrashInfoToFile(Throwable throwable) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : information.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key).append("=").append(value).append("\n");
        }
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        throwable.printStackTrace(printWriter);
        Throwable cause = throwable.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
        try {
            String time = dateFormat.format(new Date());
            String fileName = "lll" + time + ".log";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                String path = Folder.CRASH;
                File dir = new File(path);
                if (!dir.exists() && dir.mkdirs()) {
                    FileOutputStream fos = new FileOutputStream(path + fileName);
                    fos.write(sb.toString().getBytes());
                    Timber.d(sb.toString());
                    fos.close();
                } else {
                    FileOutputStream fos = new FileOutputStream(path + fileName);
                    fos.write(sb.toString().getBytes());
                    Timber.d(sb.toString());
                    fos.close();
                }
            }
        } catch (Exception e) {
            Timber.e(e);
        }
    }
}

Application

CrashManagerInitConfigure.getInstance(this);

弹窗

需跳页实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

snpmyn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值