【问题标题】:ACRA : How can I write ACRA report to file (in SD Card)?ACRA:如何将 ACRA 报告写入文件(在 SD 卡中)?
【发布时间】:2012-02-16 18:05:39
【问题描述】:

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

但我想要什么..

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

为什么我想要这个..

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

【问题讨论】:

    标签: android file crash-reports forceclose


    【解决方案1】:

    我认为您想要实现的目标已经由 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;
    }
    
    }
    

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

    【讨论】:

    • 非常感谢user1102206,您知道吗,我们如何在重新启动[重新打开应用程序]后通过单击活动中的按钮将那些写入文件的曲目发送到服务器?而不是自动发送报告。 要求:经过全面测试。请更新答案。 b'coz没有找到关于此的好帖子..所以它对其他人也更有帮助..
    • 谢谢巴亚。关于您对 ACRA 的最初问题,首先回答您的问题:如果您的应用程序崩溃,ACRA 将自行处理互联网连接可用性,无需手动处理。关于发送报告,在 acra 网站上有一些可用的东西(这里:code.google.com/p/acra/source/browse/trunk/acra/src/main/java/…)。顺便说一句,上面的代码是受类之一的启发。我所说的完全测试的意思是边缘情况:设备上没有剩余空间用于报告,没有权限在 sdcard 上写入,acra 配置设置不正确,等等。
    • 已弃用的解决方案,请参阅@user2302510 答案
    【解决方案2】:

    我猜@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;
        }
    
    }
    

    【讨论】:

    • 谢谢!这对我有用,这里有一个块副本,并且 eclipse 修复了丢失的导入。写入的文件进入 sdcard 的根目录,大小为 27k。强烈推荐!
    【解决方案3】:

    我使用过 ACRA,但不是以这种形式(用于将日志发送到我自己的服务器),所以我不确定如何执行此操作。
    但是在这种情况下,您无法获取系统日志作为整个(这将是一个详细的)使用其他库/api并将其写入文件。

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

    我说的是它的版本 4.2.3。

    【讨论】:

      【解决方案4】:

      上述解决方案完美运行。大概只有一件事, 如果使用文件资源管理器看不到文件,请尝试将意图广播添加到 Intent.ACTION_MEDIA_SCANNER_SCAN_FILE

      check this link

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多