АКРА: Как я могу записать отчет АКРА в файл (на SD-карте)? - PullRequest
7 голосов
/ 23 января 2012

Я могу использовать Библиотека ACRA для управления ошибкой принудительного закрытия путем обработки необработанного исключения.Отчет может быть успешно отправлен в Google документ, электронную почту и пользовательский веб-сервис ..

Но что я хочу ..

  • Как мне написать отчет в файл [ех.sdcard / myapp / myLog.txt]?

почему я хочу это ..

  • Пользователь моего приложения может не иметь подключения к Интернету при принудительном закрытиипроисходит .. если так, то я пропущу отчет, если я запишу отчет в файл, я смогу отправить его на сервер, когда будет доступно интернет-соединение.

Ответы [ 4 ]

8 голосов
/ 23 января 2012

Я думаю, что вы хотите достичь, уже сделано 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;
}

}

Я еще не полностью протестировал это, но вы поняли идею.Надеюсь, это поможет.

6 голосов
/ 19 июня 2014

Я думаю, что ответ от @ Gomoku7 содержит устаревший код, поэтому я просто опубликую решение, которое я использовал:

Вызовите это в onCreate ():

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

Здесь я в основном изменил код для использования BufferedWriter, чтобы я мог записывать напрямую на SD-карту, что было невозможно с openFileOutput(). Поэтому только метод send() и конструктор LocalReportSender() немного изменены.

Примечание: имейте в виду, что файл журнала растет довольно быстро, поэтому убедитесь, что вы не занимает мегабайт памяти SD-карты вашего пользователя из-за файла журнала:)

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

}
0 голосов
/ 30 декабря 2014

решение выше работает отлично.Вероятно, есть только одна вещь: если файл не отображается с помощью проводника, попробуйте добавить намеренную трансляцию в Intent.ACTION_MEDIA_SCANNER_SCAN_FILE

проверьте эту ссылку

0 голосов
/ 23 января 2012

Я использовал ACRA, но не в этой форме (используется для отправки журналов на мой собственный сервер), поэтому я не уверен, как это сделать.
Но в таком случае вы не можете получить системные журналы как целом (это будет подробный курс), используя другие библиотеки libs / apis и запишите его в файл.

ИЛИ, что вы можете сделать, это использовать код zip-файла ACRA и немного его изменить, например: .Используя файл "CrashReportData.java" или "CrashReporterDialog.java" в своем пакете и получая оттуда содержимое и сохраняя его в свой файл.

Я говорю о его версии 4.2.3.

...