Android 全局错误日志捕获的工具类

--------------------- CrashHandler ---------------------
public class CrashHandler implements Thread.UncaughtExceptionHandler {


    private static CrashHandler mInstance;
    private Thread.UncaughtExceptionHandler mDefautHandler;
    private static final String TAG = "CrashHandlerTag";

    private CrashHandler() {

    }

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


    public void init() {
        mDefautHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }


    @Override
    public void uncaughtException(Thread thread, Throwable ex) {


        if (ex != null) {

            // 收集设备信息、版本信息、异常信息
            String info = collectDeviceInfo(BaseApplication.getInstance().getApplicationContext(), ex);
            // 本地存储
            saveInfo(info);
            Log.d(TAG, "已捕获到异常 ");

            //不进行延时处理的话kill不能执行完成
            new Timer().schedule(new TimerTask() {
                @Override
                public void run() {
                    // 异常已经处理,结束进程
                    Process.killProcess(Process.myPid());
                    System.exit(1);

                }
            }, 100);

        } else {
            Log.d(TAG, "没有捕获异常 ");
            //没有处理还交给系统默认的处理器
            if (mDefautHandler != null) {
                mDefautHandler.uncaughtException(thread, ex);
            }
        }

    }

    /**
     * 收集设备信息
     *
     * @param c
     * @param ex
     */
    private String collectDeviceInfo(Context c, Throwable ex) {
        Map infos = new HashMap<>();
        //收集版本信息
        try {
            PackageManager pm = c.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(c.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionCode = pi.versionCode + "";
                String versionName = TextUtils.isEmpty(pi.versionName) ? "没有版本名称" : pi.versionName;
                infos.put("versionCode", versionCode);
                infos.put("versionName", versionName);
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        //收集设备信息
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
            } catch (Exception e) {

            }
        }

        //收集异常信息
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();

        // 转化为字符串
        StringBuffer sb = new StringBuffer();
        for (Map.Entry entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }
        sb.append(result);

        return sb.toString();
    }

    /**
     * 保存异常信息到本地
     * @param infos
     */
    private void saveInfo(String infos) {
        Log.d(TAG, "输出log日志: " + infos);
        // 把采集到的信息写入到本地文件
        LogLocalUtils.writeLogToFile(infos);

    }


}

--------------------- LogLocalUtils---------------------

public class LogLocalUtils {

    private static final String TAG = "LogLocalUtils";

    private static String basePath = Environment.getExternalStorageDirectory().getPath()
            + "/Android/data/com.example.app/log/";

    /**
     * 开启全局错误日志捕获
     */
    public static void openErrorCatch() {
        CrashHandler.getInstance().init();
    }

    /**
     * 记录用户在什么时间启动的App
     * 登录成功进入菜单界面记录一次
     */
    public static void startAppRecord() {
        writeLogToFile("----------> 登录成功,进入到菜单界面了... <----------");
    }

    /**
     * 保存日志信息到log.txt文件中
     * 每次调用往log.txt文件中添加信息
     *
     * @param logMessage 日志内容
     */
    public static void writeLogToFile(String logMessage) {

        try {
            //新建多级目录
            File sdCardDir = new File(basePath);
            if (!sdCardDir.exists() && !sdCardDir.mkdirs()) {
                try {
                    sdCardDir.createNewFile();
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d(TAG, "writeLogToFile-sdCardDir.createNewFile():" + e.getMessage());
                }
            }
            //一个月创建一次日志文件
            String yearMonth = new SimpleDateFormat("yyyyMM").format(new Date());
            String fileName = "log-" + yearMonth + ".txt";
            String logFilePath = basePath + fileName;
            FileOutputStream outputStream = new FileOutputStream(new File(logFilePath), true);
            String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(new Date());
            String message =
                    "<---------------------------start---------------------------->"
                            + "\n"
                            + "\n"
                            + time + "\n"
                            + "日志信息:" + logMessage + "\n"
                            + "\n"
                            + "<---------------------------end---------------------------->"
                            + "\n"
                            + "\n"
                            + "\n"
                            + "\n";
            outputStream.write(message.getBytes());
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            Log.d(TAG, "writeLogToFile-error: " + e.getMessage());
        }

    }


    /**
     * 保存异常信息文件到sdcard中
     * 每次调用创建新文件
     *
     * @param errorLog 日志内容
     */
    public static void writeLogToSdCard(String errorLog) {

        String sdPath = basePath + "/error_log";
        //新建多级目录
        File sdCardDir = new File(sdPath);

        if (!sdCardDir.exists() && !sdCardDir.mkdirs()) {
            
            try {
                sdCardDir.createNewFile();
            } catch (Exception e) {
                e.printStackTrace();
                Log.d(TAG, "sdCardDir.createNewFile()-error:" + e.getMessage());
            }

        }

        try {
            String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS")
                    .format(new Date());
            String fileName = time + ".txt";
            //新建文件
            File saveFile = new File(sdCardDir, fileName);

            if (!saveFile.exists()) {
                saveFile.createNewFile();
            }

            final FileOutputStream outStream = new FileOutputStream(saveFile);

            if (!TextUtils.isEmpty(errorLog)) {
                String message =
                        "<---------------------------start---------------------------->"
                                + "\n"
                                + "\n"
                                + time + "\n"
                                + "日志信息:" + errorLog + "\n"
                                + "\n"
                                + "<---------------------------end---------------------------->"
                                + "\n";
                outStream.write(message.getBytes());
                outStream.close();
            }


            Log.d(TAG, "日志输出成功! ");

        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "流写入错误:" + e.toString());
        }
    }
}

如何使用?

启动全局日志捕获的事件(出现异常崩溃后,日志会输出到sdcard中):

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        //开启全局错误日志捕获
        LogLocalUtils.openErrorCatch();
    }
}

记录App启动时间的日志(看个人情况,也可以在Application中记录):

public class HomeActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        //登录成功进入Home界面后,记录一条App启动的日志
        LogLocalUtils.startAppRecord();
    }

}

你可能感兴趣的:(Android,android,java,开发语言)