3

我正在尝试设置我的应用程序,以便可以使用logback-android编写日志,然后使用ACRA将它们发送到 Google Docs 。我认为这是可能的,但我遇到的一个问题是在哪里写日志。

这两个库都需要一个硬编码的文件名,所以我不能使用getStorageDirectory(). 所以,我的第一个问题是,如果您不指定完整路径,日志会写入哪里?我是否必须指定完整路径并将其硬编码为/data/data/com.example/...

这是我的配置:

<!-- Logback configuration. -->
<logback>
<configuration>
    <appender
        name="FILE"
        class="ch.qos.logback.core.FileAppender" >
        <file>applog.log</file>
        <encoder>
            <pattern>[%method] %msg%n</pattern>
        </encoder>
    </appender>
    <appender
        name="LOGCAT"
        class="ch.qos.logback.classic.android.LogcatAppender" >
        <tagEncoder>
            <pattern>%logger{0}</pattern>
        </tagEncoder>

        <encoder>
            <pattern>[%method] %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug" >
        <appender-ref ref="FILE" />
        <appender-ref ref="LOGCAT" />
    </root>
</configuration>
</logback>

对于阿克拉:

@ReportsCrashes(formKey = "dDB4dVRlTjVWa05T..........................",
                applicationLogFile = "applog.log",
                applicationLogFileLines = 150)

但这会产生如下错误,所以很明显我确实需要一个绝对路径。我应该使用什么?

java.io.FileNotFoundException: /applog.log: open failed: EROFS (Read-only file system)

最后一个稍微不相关的问题,我希望能够打印对象地址,例如 [%object :: %method] 会显示 [MyActivity@33c0d9d :: onCreate] 或类似的东西。有没有办法做到这一点?

4

2 回答 2

0

还有另一种解决方法。

查看 ACRA 源文件LogFileCollector.java。它以下列方式打开应用程序日志文件:

if (fileName.contains("/")) {
    reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)), 1024);
} else {
    reader = new BufferedReader(new InputStreamReader(context.openFileInput(fileName)), 1024);
}

可以使用 context.openFileOutput 保存日志消息并在 ACRA 配置中指定不带路径的日志文件名。即日志文件类可以通过以下方式声明:

public class LogOnDisk {
    public static final String LOG_FILE_NAME = "custom_log";
    private final java.io.FileOutputStream _FS;
    private final java.io.PrintStream _PS;
    public LogOnDisk(Context context) throws IOException {
        _FS = context.openFileOutput(LOG_FILE_NAME, Context.MODE_PRIVATE);
        _PS = new PrintStream(_FS);
    }

    public synchronized void toLog(String message) {
        try {           
            _PS.print(message + "\n");
            _PS.flush();
        } catch (Exception ex) {
            //nothing to do
        }
    }       
}

ACRA 配置:

@ReportsCrashes(applicationLogFile = LogOnDisk.LOG_FILE_NAME)
public final class Kernel extends Application {
于 2012-12-16T07:25:18.863 回答
0

这不是解决方案,而是替代方案。

如果您有自己的日志记录层,则可以将最后 50/100/500 条日志消息存储在循环缓冲区中,并在崩溃发生时将其提供给 ACRA。

循环缓冲区实现示例:

public static final class LogRingBuffer {
    public static final int CAPACITY = 150;
    private String[] buffer = new String[CAPACITY];
    private int position = 0;
    private boolean full = false;
    public synchronized void append(String message) {cost of sync
        buffer[position] = message;
        position = (position+1)%CAPACITY;
        if (position==0) {
            full = true;
        }
    }

    public synchronized int size() {
        return full?CAPACITY:position;
    }

    public synchronized String get(int i) {
        return buffer[(position - i - 1 + CAPACITY) % CAPACITY];
    }
}

然后您必须提供日志内容作为自定义数据字段:

int bcSize = Log.logBuffer.size();
for(int i=0; i<bcSize; ++i)
    reporter.addCustomData(String.format("LOG%03d", i), Log.logBuffer.get(i));

后一个应该在您自己的异常处理程序中实现,它应该围绕 ACRA 异常处理程序......

我承认,这并不简单,但可以为您节省一些磁盘 I/O,以及 logback-android 的使用......

于 2012-11-13T12:44:03.043 回答