use of org.acra.collector.CrashReportData in project acra by ACRA.
the class ReportExecutor method execute.
/**
* Try to send a report, if an error occurs stores a report file for a later attempt.
*
* @param reportBuilder The report builder used to assemble the report
*/
public void execute(@NonNull final ReportBuilder reportBuilder) {
if (!enabled) {
ACRA.log.v(LOG_TAG, "ACRA is disabled. Report not sent.");
return;
}
// Prime this crash report with any extra data.
reportPrimer.primeReport(context, reportBuilder);
boolean sendOnlySilentReports = false;
final ReportingInteractionMode reportingInteractionMode;
if (!reportBuilder.isSendSilently()) {
// No interaction mode defined in the ReportBuilder, we assume it has been set during ACRA.initACRA()
reportingInteractionMode = config.mode();
} else {
reportingInteractionMode = ReportingInteractionMode.SILENT;
// explicitly declared as silent via handleSilentException().
if (config.mode() != ReportingInteractionMode.SILENT) {
sendOnlySilentReports = true;
}
}
final boolean shouldDisplayToast = reportingInteractionMode == ReportingInteractionMode.TOAST || (config.resToastText() != 0 && (reportingInteractionMode == ReportingInteractionMode.NOTIFICATION || reportingInteractionMode == ReportingInteractionMode.DIALOG));
final TimeHelper sentToastTimeMillis = new TimeHelper();
if (shouldDisplayToast) {
new Thread() {
/*
* (non-Javadoc)
*
* @see java.lang.Thread#run()
*/
@Override
public void run() {
Looper.prepare();
ToastSender.sendToast(context, config.resToastText(), Toast.LENGTH_LONG);
sentToastTimeMillis.setInitialTimeMillis(System.currentTimeMillis());
Looper.loop();
}
}.start();
// We will wait a few seconds at the end of the method to be sure
// that the Toast can be read by the user.
}
final CrashReportData crashReportData = crashReportDataFactory.createCrashData(reportBuilder);
// Always write the report file
final File reportFile = getReportFileName(crashReportData);
saveCrashReportFile(reportFile, crashReportData);
final SharedPreferences prefs = new SharedPreferencesFactory(context, config).create();
if (reportingInteractionMode == ReportingInteractionMode.SILENT || reportingInteractionMode == ReportingInteractionMode.TOAST || prefs.getBoolean(ACRA.PREF_ALWAYS_ACCEPT, false)) {
// Approve and then send reports now
startSendingReports(sendOnlySilentReports);
if ((reportingInteractionMode == ReportingInteractionMode.SILENT) && !reportBuilder.isEndApplication()) {
// So no need to wait around for the sender to complete.
return;
}
} else if (reportingInteractionMode == ReportingInteractionMode.NOTIFICATION) {
if (ACRA.DEV_LOGGING)
ACRA.log.d(LOG_TAG, "Creating Notification.");
createNotification(reportFile, reportBuilder);
}
final boolean showDirectDialog = (reportingInteractionMode == ReportingInteractionMode.DIALOG) && !prefs.getBoolean(ACRA.PREF_ALWAYS_ACCEPT, false);
if (shouldDisplayToast) {
// A toast is being displayed, we have to wait for its end before doing anything else.
new Thread() {
@Override
public void run() {
if (ACRA.DEV_LOGGING)
ACRA.log.d(LOG_TAG, "Waiting for " + ACRAConstants.TOAST_WAIT_DURATION + " millis from " + sentToastTimeMillis.initialTimeMillis + " currentMillis=" + System.currentTimeMillis());
final long sleep = ACRAConstants.TOAST_WAIT_DURATION - sentToastTimeMillis.getElapsedTime();
try {
// Wait a bit to let the user read the toast
if (sleep > 0L)
Thread.sleep(sleep);
} catch (InterruptedException e1) {
if (ACRA.DEV_LOGGING)
ACRA.log.d(LOG_TAG, "Interrupted while waiting for Toast to end.", e1);
}
if (ACRA.DEV_LOGGING)
ACRA.log.d(LOG_TAG, "Finished waiting for Toast");
dialogAndEnd(reportBuilder, reportFile, showDirectDialog);
}
}.start();
} else {
dialogAndEnd(reportBuilder, reportFile, showDirectDialog);
}
}
use of org.acra.collector.CrashReportData in project acra by ACRA.
the class BaseCrashReportDialog method sendCrash.
/**
* Send crash report given user's comment and email address. If none should be empty strings
*
* @param comment Comment (may be null) provided by the user.
* @param userEmail Email address (may be null) provided by the client.
*/
protected final void sendCrash(@Nullable String comment, @Nullable String userEmail) {
final CrashReportPersister persister = new CrashReportPersister();
try {
if (ACRA.DEV_LOGGING)
ACRA.log.d(LOG_TAG, "Add user comment to " + reportFile);
final CrashReportData crashData = persister.load(reportFile);
crashData.putString(USER_COMMENT, comment == null ? "" : comment);
crashData.putString(USER_EMAIL, userEmail == null ? "" : userEmail);
persister.store(crashData, reportFile);
} catch (IOException e) {
ACRA.log.w(LOG_TAG, "User comment not added: ", e);
} catch (JSONException e) {
ACRA.log.w(LOG_TAG, "User comment not added: ", e);
}
// Start the report sending task
final SenderServiceStarter starter = new SenderServiceStarter(getApplicationContext(), config);
starter.startService(false, true);
// Optional Toast to thank the user
final int toastId = config.resDialogOkToast();
if (toastId != 0) {
ToastSender.sendToast(getApplicationContext(), toastId, Toast.LENGTH_LONG);
}
}
use of org.acra.collector.CrashReportData in project acra by ACRA.
the class ReportConverter method legacyLoad.
/**
* Loads properties from the specified InputStream. The properties are of
* the form <code>key=value</code>, one property per line. It may be not
* encode as 'ISO-8859-1'.The {@code Properties} file is interpreted
* according to the following rules:
* <ul>
* <li>Empty lines are ignored.</li>
* <li>Lines starting with either a "#" or a "!" are comment lines and are
* ignored.</li>
* <li>A backslash at the end of the line escapes the following newline
* character ("\r", "\n", "\r\n"). If there's a whitespace after the
* backslash it will just escape that whitespace instead of concatenating
* the lines. This does not apply to comment lines.</li>
* <li>A property line consists of the key, the space between the key and
* the value, and the value. The key goes up to the first whitespace, "=" or
* ":" that is not escaped. The space between the key and the value contains
* either one whitespace, one "=" or one ":" and any number of additional
* whitespaces before and after that character. The value starts with the
* first character after the space between the key and the value.</li>
* <li>Following escape sequences are recognized: "\ ", "\\", "\r", "\n",
* "\!", "\#", "\t", "\b", "\f", and "\uXXXX" (unicode character).</li>
* </ul>
*
* @param reader Reader from which to read the properties of this CrashReportData.
* @return CrashReportData read from the supplied Reader.
* @throws java.io.IOException if the properties could not be read.
* @since 1.6
*/
@NonNull
private synchronized CrashReportData legacyLoad(@NonNull Reader reader) throws IOException {
int mode = NONE, unicode = 0, count = 0;
char nextChar;
char[] buf = new char[40];
int offset = 0, keyLength = -1, intVal;
boolean firstChar = true;
final CrashReportData crashData = new CrashReportData();
final BufferedReader br = new BufferedReader(reader, ACRAConstants.DEFAULT_BUFFER_SIZE_IN_BYTES);
try {
while (true) {
intVal = br.read();
if (intVal == -1) {
break;
}
nextChar = (char) intVal;
if (offset == buf.length) {
final char[] newBuf = new char[buf.length * 2];
System.arraycopy(buf, 0, newBuf, 0, offset);
buf = newBuf;
}
if (mode == UNICODE) {
final int digit = Character.digit(nextChar, 16);
if (digit >= 0) {
unicode = (unicode << 4) + digit;
if (++count < 4) {
continue;
}
} else if (count <= 4) {
// luni.09=Invalid Unicode sequence: illegal character
throw new IllegalArgumentException("luni.09");
}
mode = NONE;
buf[offset++] = (char) unicode;
if (nextChar != '\n' && nextChar != '
') {
continue;
}
}
if (mode == SLASH) {
mode = NONE;
switch(nextChar) {
case '\r':
// Look for a following \n
mode = CONTINUE;
continue;
case '
':
case '\n':
// Ignore whitespace on the next line
mode = IGNORE;
continue;
case 'b':
nextChar = '\b';
break;
case 'f':
nextChar = '\f';
break;
case 'n':
nextChar = '\n';
break;
case 'r':
nextChar = '\r';
break;
case 't':
nextChar = '\t';
break;
case 'u':
mode = UNICODE;
unicode = count = 0;
continue;
}
} else {
switch(nextChar) {
case '#':
case '!':
if (firstChar) {
while (true) {
intVal = br.read();
if (intVal == -1) {
break;
}
// & 0xff
nextChar = (char) intVal;
// required
if (nextChar == '\r' || nextChar == '\n' || nextChar == '
') {
break;
}
}
continue;
}
break;
case '\n':
if (mode == CONTINUE) {
// Part of a \r\n sequence
// Ignore whitespace on the next line
mode = IGNORE;
continue;
}
// fall into the next case
case '
':
case '\r':
mode = NONE;
firstChar = true;
if (offset > 0 || (offset == 0 && keyLength == 0)) {
if (keyLength == -1) {
keyLength = offset;
}
final String temp = new String(buf, 0, offset);
final String elementString = temp.substring(keyLength);
Element element;
try {
element = new ComplexElement(elementString);
} catch (JSONException e1) {
try {
element = new NumberElement(Double.valueOf(elementString));
} catch (NumberFormatException e2) {
if (elementString.equals("true")) {
element = new BooleanElement(true);
} else if (elementString.equals("false")) {
element = new BooleanElement(false);
} else {
element = new StringElement(elementString);
}
}
}
crashData.put(Enum.valueOf(ReportField.class, temp.substring(0, keyLength)), element);
}
keyLength = -1;
offset = 0;
continue;
case '\\':
if (mode == KEY_DONE) {
keyLength = offset;
}
mode = SLASH;
continue;
case ':':
case '=':
if (keyLength == -1) {
// if parsing the key
mode = NONE;
keyLength = offset;
continue;
}
break;
}
if (Character.isWhitespace(nextChar)) {
if (mode == CONTINUE) {
mode = IGNORE;
}
// if key length == 0 or value length == 0
if (offset == 0 || offset == keyLength || mode == IGNORE) {
continue;
}
if (keyLength == -1) {
// if parsing the key
mode = KEY_DONE;
continue;
}
}
if (mode == IGNORE || mode == CONTINUE) {
mode = NONE;
}
}
firstChar = false;
if (mode == KEY_DONE) {
keyLength = offset;
mode = NONE;
}
buf[offset++] = nextChar;
}
if (mode == UNICODE && count <= 4) {
// luni.08=Invalid Unicode sequence: expected format \\uxxxx
throw new IllegalArgumentException("luni.08");
}
if (keyLength == -1 && offset > 0) {
keyLength = offset;
}
if (keyLength >= 0) {
final String temp = new String(buf, 0, offset);
final ReportField key = Enum.valueOf(ReportField.class, temp.substring(0, keyLength));
String value = temp.substring(keyLength);
if (mode == SLASH) {
value += "