适用于Android应用的文件记录器

时间:2013-10-30 18:01:39

标签: java android logging

我希望最简单的记录器只是将错误(主要是异常)记录到android文件系统中的Log文件中。例如,我用来登录PC上的文件的最简单和最方便(至少在我看来)的方式是简单地将所有异常打印到控制台并将系统重定向到控制台和我的文件,这不是真的足够在Android上,据我所知,我猜它是因为Android操作系统的设计方式,所以在Android中最简单的方法是什么?

请注意,该项目中已经有很多代码,我真的不想重复它并在catch块上添加日志调用或者记录我的异常,因为我需要做的少量记录这些异常是最好的我的用例...

非常感谢!

1 个答案:

答案 0 :(得分:0)

它没有完成,但工作相当稳定。它保存了人类可读的json数组,包括异常名称,时间,堆栈跟踪和其他数据。您还可以保存logcat的日志。

ExceptionWriter ew = new ExceptionWriter(new File(Environment.getExternalStorageDirectory(), "debug.txt"));
ew.w(new IllegalArgumentException("some msg"), "additional message");

<强>来源

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * User: elevenetc
 * Date: 10/9/13
 * Time: 12:52 PM
 */
public class ExceptionWriter {

    private final StringBuilder sb;
    private final ExceptionWriter.WriteExceptionTask writeExceptionTask;
    private final SimpleDateFormat dataFormat;
    private int totalExceptions;
    private StringBuilder stackBuilder = new StringBuilder();

    public int getTotalExceptions(){return totalExceptions;}

    public ExceptionWriter(File file) throws IOException {
        if(file != null){
            writeExceptionTask = new WriteExceptionTask(file);
            sb = new StringBuilder();
            dataFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
            new Thread(writeExceptionTask).start();
        }else{
            sb = null;
            writeExceptionTask = null;
            dataFormat = null;
        }

    }

    public synchronized int wLogcat(){
        try {
            writeExceptionTask.addStreamToRead(Runtime.getRuntime().exec("logcat -d -v time").getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return 0;
    }

    public int w(Exception debugException, String caughtMessage){
        return w(debugException, caughtMessage, null);
    }

    public synchronized int w(Exception debugException, String caughtMessage, String additionalData){

        if(writeExceptionTask == null) return -1;

        sb.setLength(0);

        StackTraceElement[] stackTrace = debugException == null ? null : debugException.getStackTrace();

        sb.append("{\"date\":\"");sb.append(getTime());
        sb.append("\",\"exceptionClassName\":\"");sb.append(debugException == null ? null : debugException.getClass());
        sb.append("\",\"exceptionMessage:\":\"");sb.append(debugException == null ? null : debugException.getMessage());
        sb.append("\",\"caughtMessage:\":\"");sb.append(caughtMessage);
        if(additionalData != null) {sb.append("\",\"data:\":\"");sb.append(additionalData);}
        sb.append("\",\"stack\":");sb.append(stackToString(stackTrace));
        sb.append("},");

        writeExceptionTask.stringQueue.add(sb.toString());

        totalExceptions++;

        return 0;
    }

    public void destroy() {
        if(writeExceptionTask != null) {
            writeExceptionTask.stop();
        }
    }

    private String getTime(){
        return dataFormat.format(System.currentTimeMillis());
    }

    private String stackToString(StackTraceElement[] stackTrace){

        if(stackTrace == null) return null;

        stackBuilder.setLength(0);

        stackBuilder.append("[");
        for (int i = 0; i < stackTrace.length; i++) {
            StackTraceElement e = stackTrace[i];

            stackBuilder.append("{\"");
            stackBuilder.append(e.getLineNumber());
            stackBuilder.append("\":\"");
            stackBuilder.append(e.getClassName());
            stackBuilder.append(".");
            stackBuilder.append(e.getMethodName());
            stackBuilder.append("\"}");

            if(i != stackTrace.length -1) stackBuilder.append(",");
        }
        stackBuilder.append("]");
        return stackBuilder.toString();
    }

    ///////////////////////////////////////////////
    /// Static classes
    ///////////////////////////////////////////////

    private class WriteExceptionTask implements Runnable {

        private final File file;
        private boolean running;
        private final ConcurrentLinkedQueue<String> stringQueue;
        private final ConcurrentLinkedQueue<InputStream> isQueue;
        private final FileWriter writer;

        private WriteExceptionTask(File file) throws IOException {
            this.file = file;
            writer = new FileWriter(this.file, true);
            stringQueue = new ConcurrentLinkedQueue<String>();
            isQueue = new ConcurrentLinkedQueue<InputStream>();
            running = true;
        }

        public void addStreamToRead(InputStream is){
            if(is != null){
                isQueue.add(is);
            }
        }

        @Override
        public void run() {
            while(running){
                if(!stringQueue.isEmpty()){

                    //TODO check file existence

                    try {
                        writer.append(stringQueue.poll());
                        writer.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                        running = false;
                    }
                }

                if(!isQueue.isEmpty()){
                    InputStream is = isQueue.poll();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));

                    StringBuilder builder = new StringBuilder("{\"catLog\":\"");

                    String aux;

                    try {

                        while ((aux = reader.readLine()) != null) {
                            //TODO view like array or \n
                            builder.append(aux);
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    builder.append("\"},");

                    stringQueue.add(builder.toString());
                }
            }

            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void stop() {
            running = false;
        }
    }

}