Android 崩溃日志处理

      Android app一崩溃主要看的还是LOG,获取LOG的主要途径就是Thread.UncaughtExceptionHandler接口,这个接口会在程序崩溃后捕捉到异常返回,但是我们有时候需要的是跟我们在电脑上调试看到的LOG一样,Thread.UncaughtExceptionHandler返回的是你程序出错的方法的地方,如果一个程序的方法里面有很多行,估计还是效率低;这时候就需要如下方式对崩溃日志进行补充。

PrintWriter printWriter = new PrintWriter(fileWriter);
e.printStackTrace(printWriter);//e:异常类
printWriter.flush();


使用方法:

public class MyApplication extends FrameApplication <span style="color:#ff0000;">implements OnSaveErrorLogListener</span> {

    @Override
    public void onCreate() {
        super.onCreate();
        new CaughtExceptionTool().init(this, this);
    }

    @Override
    public void onSaveErrorLogSuccess(File file) {
       <span style="color:#ff0000;">//你可以上传文件到服务器、发送邮件到自己的Email(Email工具类我博客里面也有)</span>
    }

    @Override
    public void onSaveErrorLogFail(String error) {

    }
}

异常处理工具类:

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import cn.elvetrees.frame.utils.app.PathTool;


/**
 * Created by ElveTrees on 2016/9/6.
 * 捕捉异常工具
 */
public class CaughtExceptionTool implements Thread.UncaughtExceptionHandler {


    private Context context;
    //线程超时操作
    private Future<?> future;
    //保存日志的文件夹
    private String folderName = "ErrorLog";
    //日期格式化
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
    //保存日志的文件名
    private String fileName = simpleDateFormat.format(Calendar.getInstance().getTime());
    //时间
    private String time = simpleDateFormat.format(Calendar.getInstance().getTime());
    //文件保存格式
    private String fileType = ".txt";
    //写入的文字结果
    //保存错误日志监听
    private OnSaveErrorLogListener onSaveErrorLogListener;
    //保存日志超时线程池
    private ExecutorService threadPool = Executors.newSingleThreadExecutor();
    //捕捉异常对象类
    private Thread.UncaughtExceptionHandler uncaughExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

    public CaughtExceptionTool() {

    }


    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        this.context = context;
        //设置捕捉异常监听
        Thread.setDefaultUncaughtExceptionHandler(this);
    }




    /**
     * 初始化
     *
     * @param context
     * @param onSaveErrorLogListener 保存奔溃日志的回调函数
     */
    public void init(Context context, OnSaveErrorLogListener onSaveErrorLogListener) {
        this.context = context;
        this.onSaveErrorLogListener = onSaveErrorLogListener;
        //设置捕捉异常监听
        Thread.setDefaultUncaughtExceptionHandler(this);
    }


    /**
     * 初始化
     *
     * @param context
     * @param folderName             保存奔溃日志的文件夹名
     * @param fileName               保存奔溃日志的文件名
     * @param fileType               保存奔溃日志的文件后缀名
     * @param onSaveErrorLogListener 保存奔溃日志的回调函数
     */
    public void init(Context context, String folderName, String fileName, String fileType, OnSaveErrorLogListener 


onSaveErrorLogListener) {
        this.context = context;
        this.folderName = folderName;
        this.fileName = fileName;
        this.fileType = fileType;
        this.onSaveErrorLogListener = onSaveErrorLogListener;
        //设置捕捉异常监听
        Thread.setDefaultUncaughtExceptionHandler(this);
    }


    /**
     * 获取奔溃异常
     *
     * @param thread
     * @param ex
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        Log.i("ElveTrees", this.getClass().getSimpleName() + obtainDeviceInfo() + "\n uncaughtException :" + 


ex.toString());
        if (PathTool.isExistSDCard()) {
            final File file = new File(PathTool.createFilePath(PathTool.getSDCardPath() + File.separator + 


folderName, fileName + fileType));
            //保存错误的日志
            saveErrorInfo(obtainDeviceInfo(), file, ex);
            future = threadPool.submit(new Runnable() {
                public void run() {
                    if (onSaveErrorLogListener != null) {
                        onSaveErrorLogListener.onSaveErrorLogSuccess(file);
                    }
                }
            });
            if (!future.isDone()) {
                try {
                    future.get();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            uncaughExceptionHandler.uncaughtException(thread, ex);
        } else {
            if (onSaveErrorLogListener != null) {
                onSaveErrorLogListener.onSaveErrorLogFail("You Sdcard is not exist!");
            }
            Log.e("ElveTrees", this.getClass().getSimpleName() + " You Sdcard is not exist! ");
        }
    }


    /**
     * 获取设备信息
     *
     * @return
     */
    private String obtainDeviceInfo() {
        StringBuilder sb = new StringBuilder();
        //项目信息
        sb.append("\n[==Application Information==]").append('\n');
        PackageManager packageManager = context.getPackageManager();
        ApplicationInfo ai = context.getApplicationInfo();
        //项目名字
        sb.append("Application Name : ").append(packageManager.getApplicationLabel(ai)).append('\n');
        try {
            PackageInfo pi = packageManager.getPackageInfo(ai.packageName, 0);
            //项目版本号
            sb.append("Application Version Code: ").append(pi.versionCode).append('\n');
            //项目版本名
            sb.append("Application Version Name: ").append(pi.versionName).append('\n');
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        //设备信息
        sb.append('\n').append("[==Device Information==]").append('\n');
        //手机品牌
        sb.append("Brand: ").append(Build.BRAND).append('\n');
        //设备名
        sb.append("Device: ").append(Build.DEVICE).append('\n');
        //手机版本
        sb.append("Version Code: ").append(Build.DISPLAY).append('\n');
        //指纹
        sb.append("Fingerprint: ").append(Build.FINGERPRINT).append('\n');
        //制造商
        sb.append("Manufacturer: ").append(Build.MANUFACTURER).append('\n');
        //产品名
        sb.append("Product: ").append(Build.PRODUCT).append('\n');
        return sb.toString();
    }


    /**
     * 同步保存错误日志
     *
     * @param deviceInfo 设备信息
     * @param file       保存错误信息的文件
     * @param ex         保存错误信息
     */
    private synchronized void saveErrorInfo(String deviceInfo, File file, Throwable ex) {
        synchronized (file) {
            FileWriter fileWriter = null;
            BufferedWriter bufferedWriter = null;
            PrintWriter printWriter = null;
            try {
                fileWriter = new FileWriter(file);
                bufferedWriter = new BufferedWriter(fileWriter);
                printWriter = new PrintWriter(fileWriter);
                //拼接应用、设备信息和错误Log
                bufferedWriter.append(time).append(" ").append("Error").append('/').append("Log").append(" 


").append(deviceInfo).append("\n [==Error information==]\n").append(ex.toString());
                bufferedWriter.flush();
                ex.printStackTrace(printWriter);
                printWriter.flush();
                fileWriter.flush();
            } catch (IOException e) {
                e.printStackTrace();
                closeWriter(fileWriter);
                closeWriter(bufferedWriter);
                closeWriter(printWriter);
            }
        }
    }


    /**
     * 关闭写入流通道
     *
     * @param closeable
     */
    public static void closeWriter(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException ioe) {
                Log.i("ElveTrees", CaughtExceptionTool.class.getClass().getSimpleName() + " " + ioe.toString());
            }
        }
    }


}

保存日志监听类:

import java.io.File;

/**
 * Created by ElveTrees on 2016/9/6.
 * 保存错误日志的监听
 */

public interface OnSaveErrorLogListener {

    /**
     * 保存错误日志成功回调函数
     *
     * @param file 保存错误日志的文件
     */
    void onSaveErrorLogSuccess(File file);

    /**
     * 保存错误日志失败的回调函数
     *
     * @param error 错误信息
     */
    void onSaveErrorLogFail(String error);

}


猜你喜欢

转载自blog.csdn.net/u012127961/article/details/52459255