Android Crash监控

Crash(应用崩溃)是由于代码异常而导致 App 非正常退出,导致应用程序无法继续使用,所有工作都
停止的现象。发生 Crash 后需要重新启动应用(有些情况会自动重启),而且不管应用在开发阶段做得
多么优秀,也无法避免 Crash 发生,特别是在 Android 系统中,系统碎片化严重、各 ROM 之间的差
异,甚至系统Bug,都可能会导致Crash的发生.

package com.example.crash;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    //文件后缀名
    public static final String FILE_NAME_SUFFIX = ".trace";

    private static Thread.UncaughtExceptionHandler mDefalutCrashHandler;

    private static Context context;

    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    private static class Singleton{
        public static final CrashHandler INSTNCE=new CrashHandler();
    }

    public CrashHandler() {
    }

    public static CrashHandler getInstance(){
        return Singleton.INSTNCE;
    }


    public void init(@NonNull Context context) {
        //默认为 RuntimeInit#KillApplicationHandler
        mDefalutCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
        this.context=context.getApplicationContext();

    }

    @Override
    public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
        Log.e("filesDir","uncaughtException +++++++++++++++++++++++++++++++++++++ ");
        try {

            new Thread() {
                @Override
                public void run() {
                    Looper.prepare();
                    Toast.makeText(context, "很抱歉,程序出现异常,正在收集日志,即将退出", Toast.LENGTH_LONG)
                            .show();
                    Looper.loop();
                }
            }.start();
            //自行处理
            File file = dealException(e, t);

            //上传服务器

        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            //交给系统默认程序处理
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e1) {
                Log.e("filesDir", "error : ", e1);
            }
            // 退出程序
            if (mDefalutCrashHandler != null) {
                mDefalutCrashHandler.uncaughtException(t, e);
            }
        }
    }

    /**
     * 到处异常处理消息到SD卡
     *
     * @param e
     * @param t
     * @return
     */
    private File dealException(Throwable e, Thread t) {

        String time = dateFormat.format(new Date());

       // File file = new File(context.getExternalCacheDir().getAbsoluteFile(), "crash_info");
        File file = new File(context.getCacheDir().getAbsoluteFile(), "crash_info");
        if (!file.exists()) {
            file.mkdirs();
        }
        File crashFile = new File(file, time + FILE_NAME_SUFFIX);

        //往文件中写入数据
        PrintWriter pw=null;
        try {
            pw = new PrintWriter(new BufferedWriter(new FileWriter(crashFile)));
            pw.println(time);
            pw.println("thread : " + t.getName());
            pw.println(getPhoneInfo());
            e.printStackTrace(pw);

        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (PackageManager.NameNotFoundException ex) {
            ex.printStackTrace();
        } finally {
            if (null!=pw){
            pw.flush();
            pw.close();
            }
        }

        return crashFile;
    }

    private String getPhoneInfo() throws PackageManager.NameNotFoundException {

        PackageManager pm=context.getPackageManager();
        PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);

        StringBuilder builder=new StringBuilder();

        //App版本号
        builder.append("APP Version :");
        builder.append(packageInfo.versionName);
        builder.append("_");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            builder.append(packageInfo.getLongVersionCode());
        }else {
            builder.append(packageInfo.versionCode);
        }
        builder.append("\n");

        //Android版本号
         builder.append("OS version :");
         builder.append(Build.VERSION.RELEASE);
         builder.append("_");
         builder.append(Build.VERSION.SDK_INT);
         builder.append("\n");

         //手机制造商
        builder.append("Vendor : ");
        builder.append(Build.MANUFACTURER);
        builder.append("\n");

        //手机型号
        builder.append("Model : ");
        builder.append(Build.MODEL);
        builder.append("\n");



      return builder.toString();
    }
}

直接在application中调用

public class MyApplication extends Application {
    private static MyApplication instance;
   

    public static MyApplication getInstance() {
        return instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;

        CrashHandler.getInstance().init(this);

       
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值