7

我可以使用ACRA 库通过处理未捕获的异常来管理强制关闭错误。报告可以成功发送到谷歌文档、电子邮件和自定义网络服务。

但是我想要的..

  • 如何将报告写入文件 [例如。sdcard/myapp/myLog.txt] ?

为什么我要这个..

  • 我的应用程序用户在强制关闭时可能没有互联网连接.. 如果是这样,我会错过报告,如果我将报告写入文件,那么当互联网连接可用时,我可以发送到我的服务器。
4

4 回答 4

8

我认为您想要实现的目标已经由 ACRA 完成。这是我在 abd logcat 中看到的内容:

01-23 12:15:28.056: D/ACRA(614): Writing crash report file.
01-23 12:15:28.136: D/ACRA(614): Mark all pending reports as approved.
01-23 12:15:28.136: D/ACRA(614): Looking for error files in /data/data/com.ybi/files
01-23 12:15:28.136: V/ACRA(614): About to start ReportSenderWorker from #handleException
01-23 12:15:28.146: D/ACRA(614): Add user comment to null
01-23 12:15:28.146: D/ACRA(614): #checkAndSendReports - start
01-23 12:15:28.146: D/ACRA(614): Looking for error files in /data/data/com.ybi/files

ACRA 做的第一件事是在你的应用程序的内部存储上创建一个文件报告。然后,如果您在线并且错误报告器已正确初始化,它会发送报告。否则,报告将保存在数据存储中(供以后发送)。

我没有查看数据,但我目前正在开发自定义记录器。因此,如果您想做与 ACRA 相同的事情,这很容易:

    ACRA.init(this);

    // a custom reporter for your very own purposes
    ErrorReporter.getInstance().setReportSender(new LocalReportSender(this));

接着 :

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.acra.ACRA;
import org.acra.CrashReportData;
import org.acra.ReportField;
import org.acra.sender.ReportSender;
import org.acra.sender.ReportSenderException;

import android.content.Context;

import de.akquinet.android.androlog.Log;

public class LocalReportSender implements ReportSender {

private final Map<ReportField, String> mMapping = new HashMap<ReportField, String>() ;
private FileOutputStream crashReport = null; 

public LocalReportSender(Context ctx) {
    // the destination
    try {
        crashReport = ctx.openFileOutput("crashReport", Context.MODE_WORLD_READABLE);
    } catch (FileNotFoundException e) {
        Log.e("TAG", "IO ERROR",e);
    }
}

@Override
public void send(CrashReportData report) throws ReportSenderException {

    final Map<String, String> finalReport = remap(report);

    try {
        OutputStreamWriter osw = new OutputStreamWriter(crashReport);

        Set set = finalReport.entrySet();
        Iterator i = set.iterator();

        while (i.hasNext()) {
            Map.Entry<String,String> me = (Map.Entry) i.next();
            osw.write("[" + me.getKey() + "]=" + me.getValue());
        }

        osw.flush();
        osw.close();
    } catch (IOException e) {
        Log.e("TAG", "IO ERROR",e);
    }

}

private static boolean isNull(String aString) {
    return aString == null || ACRA.NULL_VALUE.equals(aString);
}

private Map<String, String> remap(Map<ReportField, String> report) {

    ReportField[] fields = ACRA.getConfig().customReportContent();
    if (fields.length == 0) {
        fields = ACRA.DEFAULT_REPORT_FIELDS;
    }

    final Map<String, String> finalReport = new HashMap<String, String>(
            report.size());
    for (ReportField field : fields) {
        if (mMapping == null || mMapping.get(field) == null) {
            finalReport.put(field.toString(), report.get(field));
        } else {
            finalReport.put(mMapping.get(field), report.get(field));
        }
    }
    return finalReport;
}

}

我还没有完全测试它,但你明白了。希望能帮助到你。

于 2012-01-23T11:53:18.570 回答
6

我猜@Gomoku7 的答案包含一些已弃用的代码,所以我将发布我使用的解决方案:

在 onCreate() 中调用它:

ACRA.init(this);
ACRA.getErrorReporter().setReportSender(new LocalReportSender(this));

在这里,我基本上将代码更改为使用 BufferedWriter,这样我就可以直接写入 SD 卡,而openFileOutput(). 因此只有方法send()和构造函数LocalReportSender()略有改变。

注意:请注意日志文件增长得非常快,因此请确保您不会因为日志文件而占用用户 SD 卡的 MB 空间 :)

private class LocalReportSender implements ReportSender {

    private final Map<ReportField, String> mMapping = new HashMap<ReportField, String>();
    private FileWriter crashReport = null;

    public LocalReportSender(Context ctx) {
        // the destination
        File logFile = new File(Environment.getExternalStorageDirectory(), "log.txt");

        try {
            crashReport = new FileWriter(logFile, true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void send(CrashReportData report) throws ReportSenderException {
        final Map<String, String> finalReport = remap(report);

        try {
            BufferedWriter buf = new BufferedWriter(crashReport);

            Set<Entry<String, String>> set = finalReport.entrySet();
            Iterator<Entry<String, String>> i = set.iterator();

            while (i.hasNext()) {
                Map.Entry<String, String> me = (Entry<String, String>) i.next();
                buf.append("[" + me.getKey() + "]=" + me.getValue());
            }

            buf.flush();
            buf.close();
        } catch (IOException e) {
            Log.e("TAG", "IO ERROR", e);
        }
    }

    private boolean isNull(String aString) {
        return aString == null || ACRAConstants.NULL_VALUE.equals(aString);
    }

    private Map<String, String> remap(Map<ReportField, String> report) {

        ReportField[] fields = ACRA.getConfig().customReportContent();
        if (fields.length == 0) {
            fields = ACRAConstants.DEFAULT_REPORT_FIELDS;
        }

        final Map<String, String> finalReport = new HashMap<String, String>(
                report.size());
        for (ReportField field : fields) {
            if (mMapping == null || mMapping.get(field) == null) {
                finalReport.put(field.toString(), report.get(field));
            } else {
                finalReport.put(mMapping.get(field), report.get(field));
            }
        }
        return finalReport;
    }

}
于 2014-06-19T11:34:15.957 回答
0

我使用过 ACRA,但不是以这种形式(用于将日志发送到我自己的服务器),所以我不知道该怎么做。
但在这种情况下,您不能使用其他库/api 获取整个系统日志(这将是一个详细的日志)并将其写入文件。

或者,您可以做的是,使用 ACRA zip 的代码并对其进行一些修改,例如。使用其包中的文件“CrashReportData.java”或“CrashReporterDialog.java”并从那里获取内容并将其保存到你的文件。

我说的是它的 4.2.3 版本。

于 2012-01-23T11:51:35.453 回答
0

上面的解决方案完美无缺。可能只有一件事,如果使用文件资源管理器看不到文件,请尝试将意图广播添加到 Intent.ACTION_MEDIA_SCANNER_SCAN_FILE

检查这个链接

于 2014-12-30T13:17:28.867 回答