ACRA: How can I write an ACRA report to a file (on an SD card)?

I can use the ACRA library to manage syntax closure errors by handling an uncaught exception. The report can be successfully sent to google doc., Email and user web service.

But what I want ..

  • How to write a report to the file [ex. sdcard / myapp / myLog.txt]?

why do I want this.

  • A user of my application may not have an internet connection when a forced closure occurs . If so, I will skip the report, if I write the report to a file, then I can send it to my server when an Internet connection is available.
+7
source share
4 answers

I think what you want to achieve has already been done by ACRA. Here is what I see in my 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 

The first thing ACRA does is to create a file report on the internal memory of your application. Then, if you are connected to the network and the error correction is correctly initialized, it sends a report. Otherwise, the reports are stored in the data warehouse (for subsequent sending).

I did not view the data, but now I am working on a special registrar. Therefore, if you want to do the same as ACRA, it is easy:

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

And then:

 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; } } 

I have not fully tested it yet, but you understood this idea. Hope this helps.

+8
source

I think the answer from @ Gomoku7 contains some legacy code, so I will just post the solution I used:

Call this in onCreate ():

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

Here I basically changed the code to use BufferedWriter so that I could write directly to the SD card, which was not possible with openFileOutput() . Therefore, only the send() method and the LocalReportSender() constructor LocalReportSender() slightly modified.

Note. Keep in mind that the log file is growing quite fast, so be sure to take the MBs of your user's SD card space because of the log file :)

 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; } } 
+6
source

I used ACRA, but not in this form (used to send logs to my own server), so I'm not sure how to do this.
But in this case, you will not be able to get system logs as (which will be described in detail in any case) using other libs / apis and writing them to a file.

OR, what you can do is use the ACRA zip code and modify it a little. Using the file "CrashReportData.java" or "CrashReporterDialog.java" in your package and getting it from there and saving it to a file.

I am talking about its version 4.2.3.

0
source

The solution above works fine. There is probably only one thing. If the file is not displayed using the file explorer, try adding the intent translation to Intent.ACTION_MEDIA_SCANNER_SCAN_FILE

check this link

0
source

All Articles