Wie kann ich Absturzdaten (zumindest Stack Traces) von meiner Android-Anwendung erhalten? Zumindest bei der Arbeit auf meinem eigenen Gerät wird durch Kabel abgerufen, aber idealerweise von jeder Instanz meiner Anwendung läuft auf der wilden, so dass ich es verbessern und machen es mehr solide.
Antworten
Zu viele Anzeigen?Versuchen Sie die ACRA (Anwendungsabsturzbericht für Android) Bibliothek:
ACRA ist eine Bibliothek, die es Android-Anwendungen ermöglicht, ihre Unfallberichte automatisch in einem GoogleDoc-Formular zu veröffentlichen. Sie richtet sich an Entwickler von Android-Anwendungen, um ihnen zu helfen, Daten von ihren Anwendungen zu erhalten, wenn diese abstürzen oder sich fehlerhaft verhalten.
Es ist einfach in Ihrer Anwendung zu installieren, hochgradig konfigurierbar und Sie müssen nirgendwo ein Serverskript hosten... Berichte werden an ein Google Doc Spreadsheet gesendet!
Für Beispielanwendungen und Debugging-Zwecke verwende ich eine einfache Lösung, die es mir ermöglicht, den Stacktrace auf die SD-Karte des Geräts zu schreiben und/oder ihn auf einen Server hochzuladen. Diese Lösung wurde inspiriert von Project Android-Remote-Stacktrace (insbesondere die Teile "Speichern auf dem Gerät" und "Hochladen auf den Server") und ich denke, dass damit das von Soonil erwähnte Problem gelöst ist. Es ist nicht optimal, aber es funktioniert, und Sie können es verbessern, wenn Sie es in einer Produktionsanwendung verwenden möchten. Wenn Sie sich entscheiden, die Stacktraces auf den Server hochzuladen, können Sie ein php-Skript verwenden ( index.php
), um sie zu sehen. Wenn Sie Interesse haben, finden Sie unten alle Quellen - eine Java-Klasse für Ihre Anwendung und zwei optionale php-Skripte für den Server, der die hochgeladenen Stacktraces hostet.
Rufen Sie in einem Kontext (z. B. der Hauptaktivität)
if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(
"/sdcard/<desired_local_path>", "http://<desired_url>/upload.php"));
}
CustomExceptionHandler
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
private String localPath;
private String url;
/*
* if any of the parameters is null, the respective functionality
* will not be used
*/
public CustomExceptionHandler(String localPath, String url) {
this.localPath = localPath;
this.url = url;
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
public void uncaughtException(Thread t, Throwable e) {
String timestamp = TimestampFormatter.getInstance().getTimestamp();
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
String filename = timestamp + ".stacktrace";
if (localPath != null) {
writeToFile(stacktrace, filename);
}
if (url != null) {
sendToServer(stacktrace, filename);
}
defaultUEH.uncaughtException(t, e);
}
private void writeToFile(String stacktrace, String filename) {
try {
BufferedWriter bos = new BufferedWriter(new FileWriter(
localPath + "/" + filename));
bos.write(stacktrace);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendToServer(String stacktrace, String filename) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("filename", filename));
nvps.add(new BasicNameValuePair("stacktrace", stacktrace));
try {
httpPost.setEntity(
new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
httpClient.execute(httpPost);
} catch (IOException e) {
e.printStackTrace();
}
}
}
upload.php
<?php
$filename = isset($_POST['filename']) ? $_POST['filename'] : "";
$message = isset($_POST['stacktrace']) ? $_POST['stacktrace'] : "";
if (!ereg('^[-a-zA-Z0-9_. ]+$', $filename) || $message == ""){
die("This script is used to log debug data. Please send the "
. "logging message and a filename as POST variables.");
}
file_put_contents($filename, $message . "\n", FILE_APPEND);
?>
index.php
<?php
$myDirectory = opendir(".");
while($entryName = readdir($myDirectory)) {
$dirArray[] = $entryName;
}
closedir($myDirectory);
$indexCount = count($dirArray);
sort($dirArray);
print("<TABLE border=1 cellpadding=5 cellspacing=0 \n");
print("<TR><TH>Filename</TH><TH>Filetype</th><th>Filesize</TH></TR>\n");
for($index=0; $index < $indexCount; $index++) {
if ((substr("$dirArray[$index]", 0, 1) != ".")
&& (strrpos("$dirArray[$index]", ".stacktrace") != false)){
print("<TR><TD>");
print("<a href=\"$dirArray[$index]\">$dirArray[$index]</a>");
print("</TD><TD>");
print(filetype($dirArray[$index]));
print("</TD><TD>");
print(filesize($dirArray[$index]));
print("</TD></TR>\n");
}
}
print("</TABLE>\n");
?>
In Android 2.2 ist es nun möglich, automatisch Absturzberichte von Android Market-Anwendungen zu erhalten:
Neue Fehlerberichtsfunktion für Android Market-Apps ermöglicht es Entwicklern Absturz- und Einfrierberichte von ihren Nutzern erhalten. Die Berichte werden verfügbar, wenn sie sich bei ihrem Verlagskonto anmelden.
http://developer.Android.com/sdk/Android-2.2-highlights.html
Es ist möglich, diese Ausnahmen zu behandeln mit Thread.setDefaultUncaughtExceptionHandler()
Dies scheint jedoch die Methode von Android zur Behandlung von Ausnahmen zu stören. Ich habe versucht, einen Handler dieser Art zu verwenden:
private class ExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable ex){
Log.e(Constants.TAG, "uncaught_exception_handler: uncaught exception in thread " + thread.getName(), ex);
//hack to rethrow unchecked exceptions
if(ex instanceof RuntimeException)
throw (RuntimeException)ex;
if(ex instanceof Error)
throw (Error)ex;
//this should really never happen
Log.e(Constants.TAG, "uncaught_exception handler: unable to rethrow checked exception");
}
}
Doch selbst mit dem erneuten Auslösen der Ausnahmen konnte ich nicht das gewünschte Verhalten erzielen, d. h. die Ausnahme protokollieren und gleichzeitig Android das Herunterfahren der Komponente ermöglichen, so dass ich nach einer Weile aufgegeben habe.
- See previous answers
- Weitere Antworten anzeigen
10 Stimmen
Sehen Sie sich das an: github.com/tomquist/Android-Fehler-Reporter
0 Stimmen
Ich sehe, dass der Bericht an einen entfernten Server gesendet wird. Kann es die Ausnahme auch in einer lokalen Datei protokollieren?
1 Stimmen
Anwendungsabsturzbericht für Android code.google.com/p/acra
0 Stimmen
Diese sieht zu sein, die mehr robust, was über, wenn die Berichterstattung nicht hochladen nach allen Wiederholungen, kann es dann protokollieren es Datei oder Sqlite db?
0 Stimmen
Haben Sie Firebase Crashlytics ausprobiert?