未捕获异常的处理器

package com.example.framework.manager;

import android.app.Activity;
import android.content.Context;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

import androidx.annotation.NonNull;

import com.example.net.RetrofitCreator;
import com.example.net.bean.CrashBean;

import io.reactivex.Observer;
import io.reactivex.Scheduler;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

//定义一个电商应用闪退的处理类,通过该类可以捕获到应用程序未处理的异常信息,捕获到之后,给用户提示,出现了什么错误,提升用户体验
//并且,将错误信息推送到服务端,便于开发人员获取这些信息,优化我们的应用.
public class ShopmallCrashHandler implements Thread.UncaughtExceptionHandler{
    private static ShopmallCrashHandler instance;
    private Thread.UncaughtExceptionHandler systemDefaultHandler;
    private Context applicationContext;
    private String crashPath = "/sdcard/shopmallcrash/";
    private ShopmallCrashHandler() {

    }

    public static ShopmallCrashHandler getInstance() {
        if (instance==null) {
            synchronized (ShopmallCrashHandler.class) {
                if (instance==null){
                    instance = new ShopmallCrashHandler();
                }
            }
        }
        return instance;
    }


    public void init(Context applicationContext) {
        this.applicationContext = applicationContext;
        systemDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();//先获取系统默认处理未捕获异常的处理器
        Thread.setDefaultUncaughtExceptionHandler(this);//把当前这个类作为未捕获异常的处理器

        //初始化存储错误的目录
        File crashFileDir = new File(crashPath);
        if (!crashFileDir.exists()) {
            crashFileDir.mkdir();
        }
    }

    private void saveExecptionInfo(Throwable e) {
        //将异常信息放到一个输出流里
        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        e.printStackTrace(printWriter);

        //生成一个文件名
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeStr = simpleDateFormat.format(new Date());

        File crashFile = new File(crashPath+timeStr+".txt");
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(crashFile);
            String crashStr = stringWriter.toString();
            byte[] crashByteArray = crashStr.getBytes();
            int length = crashByteArray.length;
            try {
                fileOutputStream.write(crashByteArray, 0, length);
                fileOutputStream.flush();
            } catch (IOException e1) {
                e1.printStackTrace();
            }finally {
                try {
                    fileOutputStream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }

        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }

    }


    /**
     *
     * @param t 出现未捕获异常的线程
     * @param e 异常信息.当主线程出现未捕获异常,主线程的运行流程出现不可恢复的错误,应用无法正常运行,必须把应用杀掉重新启动。如果
     *          是子线程出现了不可捕获的异常,该线程将会出现不可恢复的错误。但是主线程正常
     */
    @Override
    public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                //这个中间位置是运行在主线程的
                Toast.makeText(applicationContext,"对不起,程序运行出现了错误,请重新启动该应用!",Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }).start();

        //将错误异常上报到服务端
        HashMap<String,String> param = new HashMap<>();
        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        e.printStackTrace(printWriter);
        param.put("message",stringWriter.toString());

        RetrofitCreator.getFiannceApiService().crashReport(param)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(new Observer<CrashBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(CrashBean crashBean) {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
        saveExecptionInfo(e);

        try {
            Thread.sleep(3*1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        //杀掉该进程,需要提前把所有activity全部finish掉才可以
        for(Activity activity:CacheManager.getInstance().getActivityList()) {
            activity.finish();
        }
        System.exit(1);//该方法可以杀掉进程


    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值