Android程序Crash统计

本文介绍了一种在Android应用中捕获并记录程序崩溃信息的方法。通过实现自定义的CrashHandler,可以在程序崩溃时自动收集设备信息及异常堆栈,方便开发者定位问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


大家都知道,在开发程序时,很难做到不会crash,程序在crash后我们就要分析其原因,那么首先就得统计crash信息。 本篇文章将介绍程序在crash后,如何获取crash的信息。

创建CrashHandler


package com.crash.xxx.crashhandlertest;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Process;
import android.util.Log;

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;

/**
 * Created by xxx on 2016/8/19.
 */
public class CrashHandler implements Thread.UncaughtExceptionHandler {
    private static final boolean DEBUG=true;
    private static final String TAG="CrashHanler";

    private static final String PATH=Environment.getExternalStorageDirectory().getPath()+"/crashHandlerTest/crash_log/";
    private static final String FILE_NAME="crash_";
    private static final String FILE_NAME_SUFFIX=".trace";

    private static CrashHandler mInstance=new CrashHandler();
    private Thread.UncaughtExceptionHandler mUncaughtExceptionHandler;
    private Context mContext;

    private CrashHandler(){
    }

    public static CrashHandler getInstance(){
        return mInstance;
    }

    public void init(Context context){
        mUncaughtExceptionHandler=Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
        mContext=context.getApplicationContext();
    }

    /**
     * 当程序中有未捕捉的异常,系统自动调用此方法;
     * thread为出现异常的线程,ex为未捕捉的异常
     * @param thread
     * @param ex
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        try {
            //将导出的异常写入SD卡中
            dumpExceptionToSDCard(ex);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ex.printStackTrace();
        //如果系统提供了异常处理,则交给系统去结束程序,否则由自己的程序结束自己
        if (mUncaughtExceptionHandler!=null){
            mUncaughtExceptionHandler.uncaughtException(thread,ex);
        }else{
            Process.killProcess(Process.myPid());
        }
    }

    public void dumpExceptionToSDCard(Throwable ex) throws IOException{
        //如果sd卡存在,则将异常写入sd卡中
        if (!Environment.getExternalStorageState().endsWith(Environment.MEDIA_MOUNTED)){
            if (DEBUG){
                Log.w(TAG,"sdcard unmounted,skip dump exception");
                return;
            }
        }
        File dir=new File(PATH);
        if (!dir.exists()){
            dir.mkdirs();
        }
        long current=System.currentTimeMillis();
        String time=new SimpleDateFormat("yyyy-MM-dd").format(new Date(current));
        File file=new File(PATH+FILE_NAME+time+FILE_NAME_SUFFIX);
        try {
            PrintWriter pw=new PrintWriter(new BufferedWriter(new FileWriter(file)));
            pw.println(time);
            //写入手机信息
            dumpPhoneInfo(pw);
            pw.println();
            //写入崩溃信息
            ex.printStackTrace(pw);
            pw.close();
        } catch (Exception e) {
            e.printStackTrace();
            if (DEBUG){
                Log.e(TAG,"写入失败"+e);
            }
        }
    }

    public void dumpPhoneInfo(PrintWriter pw) throws PackageManager.NameNotFoundException{
        PackageManager pm=mContext.getPackageManager();
        PackageInfo pi=pm.getPackageInfo(mContext.getPackageName(),PackageManager.GET_ACTIVITIES);
        pw.println("APP Version:");
        pw.print(pi.versionName);
        pw.print("_");
        pw.println(pi.versionCode);
        //android version code
        pw.print("OS version: ");
        pw.print(Build.VERSION.RELEASE);
        pw.print("_");
        pw.println(Build.VERSION.SDK_INT);
        //phone makes vendor
        pw.print("Vendor: ");
        pw.println(Build.MANUFACTURER);
        //phone model
        pw.print("Model: ");
        pw.println(Build.MODEL);
        //CPU ABI
        pw.print("CPU ABI: ");
        pw.println(Build.CPU_ABI);
    }

    //将crash日志上传到服务器
    public void upLoadExceptionToServer(){

    }

}


在AppLication初始化时为线程配置CrashHandler



@Override
    public void onCreate() {
        super.onCreate();
        CrashHandler crashHandler=CrashHandler.getInstance();
        crashHandler.init(this);
    }

在清单文件中注册创建的AppLication,并添加所需的权限


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

测试

在MainActivity中创建一个Button,为其添加点击事件,在监听回调中抛一个自定义异常。

 @Override
    public void onClick(View v) {
        if (v.getId()==R.id.btn_click){
            throw new RuntimeException("自定义运行时异常");
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值