Wie erhalte ich Absturzdaten von meiner Android-Anwendung?


737

Wie kann ich Absturzdaten (mindestens Stapelspuren) von meiner Android-Anwendung abrufen? Zumindest wenn ich an meinem eigenen Gerät arbeite, das per Kabel abgerufen wird, aber idealerweise von jeder Instanz meiner Anwendung, die in freier Wildbahn ausgeführt wird, damit ich es verbessern und solider machen kann.


10
Überprüfen Sie dies heraus: github.com/tomquist/Android-Error-Reporter
Tom

Ich sehe, dass dies den Bericht an einen Remote-Server sendet. Kann es die Ausnahme auch in einer lokalen Datei protokollieren?

1
Application Crash Report für Android code.google.com/p/acra
gdonald

Dieser scheint robuster zu sein. Was ist, wenn die Berichterstellung nach allen Wiederholungsversuchen nicht hochgeladen werden kann? Kann sie dann die Datei oder die SQLite-Datenbank protokollieren?
JPM

Antworten:


354

Sie können die ACRA- Bibliothek (Application Crash Report für Android) ausprobieren :

ACRA ist eine Bibliothek, mit der Android Application ihre Absturzberichte automatisch in einem GoogleDoc-Formular veröffentlichen kann. Es richtet sich an Entwickler von Android-Anwendungen, um ihnen zu helfen, Daten aus ihren Anwendungen abzurufen, wenn sie abstürzen oder sich fehlerhaft verhalten.

Es ist einfach in Ihrer App zu installieren, hochgradig konfigurierbar und erfordert nicht, dass Sie irgendwo ein Serverskript hosten ... Berichte werden an eine Google Doc-Tabelle gesendet!


8
Dies ist einfach einzurichten und zu verwenden. Empfohlen für die Verwendung vor dem Inverkehrbringen und möglicherweise auch danach.
mxcl

1
Ich habe angefangen, es zu verwenden, und es ist unangemessen besser als die Fehlerberichterstattung in Flurry, die ich zuvor hatte, oder die hausgemachte, mit der ich angefangen habe. Bisher bin ich begeistert von "Acra".
Adrian Spinei

8
Der große Vorteil von acra ist die Möglichkeit, mithilfe von Google-APIs die Daten einfach zu analysieren und zu visualisieren. Ein Beispiel hierfür finden Sie unter jberkel.github.com/sms-backup-plus/acra-analysis .
Jan Berkel

3
Scheint mir sehr instabil zu sein. Der ACRA selbst stürzte ab und sendete einen Absturzbericht über sich selbst, nicht den zugehörigen App-Absturz. -1
Sandor

19
Google
Text

305

Für Beispielanwendungen und Debugging-Zwecke verwende ich eine einfache Lösung, mit der ich den Stacktrace auf die SD-Karte des Geräts schreiben und / oder auf einen Server hochladen kann. Diese Lösung wurde von Project android-remote-stacktrace (insbesondere den Teilen zum Speichern auf dem Gerät und zum Hochladen auf den Server) inspiriert und löst meines Erachtens das von Soonil erwähnte Problem. Es ist nicht optimal, aber es funktioniert und Sie können es verbessern, wenn Sie es in einer Produktionsanwendung verwenden möchten. Wenn Sie die Stacktraces auf den Server hochladen möchten, können Sie sie mit einem PHP-Skript ( index.php) anzeigen. Wenn Sie interessiert sind, finden Sie unten alle Quellen - eine Java-Klasse für Ihre Anwendung und zwei optionale PHP-Skripte für den Server, auf dem sich die hochgeladenen Stacktraces befinden.

Rufen Sie in einem Kontext (z. B. der Hauptaktivität) auf

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");
?>

9
Ich denke, dies wird in einigen Staaten / Ländern rechtliche Probleme verursachen
Setzamora

5
HINWEIS: HttpPost httpPost = new HttpPost(url);muss sich jetzt in einer asynchronen Aufgabe (oder einem Handler ... einem separaten Thread) befinden, wenn Sie auf Honeycomb oder höher abzielen
Bryan Denny

4
@ Joset, welche rechtlichen Probleme und warum?
Varevarao

2
@varevarao Rechtliche Probleme (möglicherweise), weil Sie vertrauliche Geräteinformationen ohne Zustimmung des Benutzers senden, indem Sie die Funktion "An Server senden" dieses Codes verwenden.
Caw

2
Der defaultExceptionHandler scheint während der gesamten Aktivitätserstellung bestehen zu bleiben. Ich habe die Antwort aktualisiert, um den Standard nur festzulegen, wenn noch kein benutzerdefinierter Handler festgelegt wurde. Ohne sie hält und ruft jeder Handler den vorherigen bis zum ursprünglichen auf. Dies führt zu Problemen bei der doppelten Protokollierung sowie zu Speicherverlustproblemen.
Dave McClelland

57

Sie können auch [BugSense] ausprobieren. Grund: Spam-Weiterleitung zu einer anderen URL . BugSense sammelt und analysiert alle Absturzberichte und liefert Ihnen aussagekräftige und visuelle Berichte. Es ist kostenlos und es ist nur 1 Codezeile, um zu integrieren.

Haftungsausschluss: Ich bin Mitbegründer


4
Ich habe BugSense ausprobiert und es ist großartig. Einfache und frische Benutzeroberfläche, auch sehr schnell. Kein dummes Aufblähen. Leicht zu erkennen, die häufigsten Abstürze und auch in die Stacktrace zu graben.
Vidstige

Wir machen in letzter Zeit viel mehr als nur Crash-Berichterstattung, aber dies ist nicht der richtige Ort, um über neue Funktionen usw. zu sprechen.
PanosJee

Ich habe es versucht. Fehler haben funktioniert, obwohl Stacktrace nicht zu vollständig ist und Echtzeit-Crash-Daten nicht durchgekommen sind. Der Debug-Modus hat nicht funktioniert. Ich habe jedoch die Route der einmaligen Initialisierung von der Anwendungsklasse aus durchlaufen (was in den meisten Fällen sinnvoll ist). BugSense hat ein erstaunliches Dashboard, eine Schande, dass Absturzberichte aus irgendeinem Grund nicht funktionieren und die Symbolisierung nicht in der kostenlosen Stufe enthalten ist. Ich habe 5 Minuten gebraucht, um GetSentry zu installieren, und es hat für Android mit diesem Allzweck-Client
sofort funktioniert

3
BugSense ist einfach und leicht zu integrieren. ABER ES IST ZU teuer. Mit Flurry Analytics und Parse können wir dieselben Bug-Sense-Funktionen erreichen. Beide sind kostenlos und einfach zu integrieren.
Venkat

44

In Android 2.2 ist es jetzt möglich, automatisch Crash-Berichte von Android Market-Anwendungen abzurufen:

Mit der neuen Funktion zur Fehlerberichterstattung für Android Market-Apps können Entwickler Absturz- und Einfrierberichte von ihren Benutzern erhalten. Die Berichte sind verfügbar, wenn sie sich bei ihrem Herausgeberkonto anmelden.

http://developer.android.com/sdk/android-2.2-highlights.html


Ich denke, es ist nicht nur 2.2, sondern einfach eine neue Marktfunktion, die Google anbietet. Ich habe vor einigen Tagen einen Crashreport bekommen und es sollte kein Froyo-Gerät mit meiner App geben.
Janusz

1
@ Janusz Bist du sicher? Es gibt bereits Veröffentlichungen von Froyo für Nexus One, ohne die Googler zu zählen, die Froyo schon eine Weile betreiben.
Pupeno

Zumindest muss es ein Update in der Version auf dem Telefon gegeben haben, sogar eine weitere Überarbeitung, aber wie sollte dies ansonsten funktionieren?
RoflcoptrException

Ich weiß nicht, ob die Berichte zuvor an Google gesendet wurden. Der Bericht ist etwas seltsam, weil Google eine Benutzeroberfläche zum Senden ihrer Videos anzeigt und dies eine Änderung des Betriebssystems und nicht nur des Marktes sein muss. Aber es heißt: Plattform 1 meldet Berichte / Woche und der Droide sollte nicht auf Froyo sein.
Janusz

1
Der Schaltflächencode "Bericht" ist seit einiger Zeit in der AOSP enthalten, und Romain Guy hat hier vor einigen Monaten (vage) eine Frage dazu beantwortet.
Christopher Orr

30

Es ist möglich, diese Ausnahmen mit zu behandeln Thread.setDefaultUncaughtExceptionHandler(), dies scheint jedoch mit der Methode von Android zur Behandlung von Ausnahmen in Konflikt zu geraten. 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");
    }
}

Selbst beim erneuten Auslösen der Ausnahmen konnte ich nicht das gewünschte Verhalten erzielen, dh die Ausnahme protokollieren, während Android die Komponente, die es passiert war, weiterhin herunterfahren konnte, sodass ich sie nach einer Weile aufgab.


Warum werfen Sie nur ungeprüfte Ausnahmen erneut? Es scheint mir, dass Sie alle Ausnahmen erneut werfen sollten.
MatrixFrog

Es sieht so aus, als ob jemand mit Ihrem Ansatz erfolgreich war: jyro.blogspot.com/2009/09/crash-report-for-android-app.html
MatrixFrog

1
Der Trick besteht darin, den vorherigen Standard-UncaughtExceptionHandler abzurufen und die Ausnahme für dieses Objekt zu behandeln, nachdem Sie die Ausnahme gemeldet haben.
Tom

Ist ein Constants.TAGTeil des Android-Frameworks? Zum ersten Mal gesehen. Kann es nicht finden.
Haroun Hajem

1
@ HarounHajem Wir müssen unsere eigenen definieren.
KYHSGeekCode

22

Ich sehe, dass die Frage zu alt ist, und hoffe, dass meine Antwort für andere hilfreich ist, die das gleiche Problem haben ...

Probieren Sie Crashlytics aus . Es gibt einen detaillierten Einblick in alle Abstürze auf allen Geräten mit Ihrer Anwendung und sendet Ihnen eine Benachrichtigung per E-Mail. Und das Beste daran ist, dass die Verwendung völlig kostenlos ist.


21

Ok, nun, ich habe mir die bereitgestellten Beispiele von rrainn und Soonil angesehen und eine Lösung gefunden, die die Fehlerbehandlung nicht durcheinander bringt.

Ich habe den CustomExceptionHandler so geändert, dass er den ursprünglichen UncaughtExceptionHandler aus dem Thread speichert, den wir dem neuen zuordnen. Am Ende der neuen "uncaughtException" -Methode rufe ich einfach die alte Funktion mit dem gespeicherten UncaughtExceptionHandler auf.

In der DefaultExceptionHandler-Klasse benötigen Sie etw. so was:

public class DefaultExceptionHandler implements UncaughtExceptionHandler{
  private UncaughtExceptionHandler mDefaultExceptionHandler;

  //constructor
  public DefaultExceptionHandler(UncaughtExceptionHandler pDefaultExceptionHandler)
  {
       mDefaultExceptionHandler= pDefaultExceptionHandler;
  }
  public void uncaughtException(Thread t, Throwable e) {       
        //do some action like writing to file or upload somewhere         

        //call original handler  
        mStandardEH.uncaughtException(t, e);        

        // cleanup, don't know if really required
        t.getThreadGroup().destroy();
  }
}

Mit dieser Änderung des Codes unter http://code.google.com/p/android-remote-stacktrace haben Sie eine gute Arbeitsbasis, um sich vor Ort bei Ihrem Webserver oder auf der SD-Karte anzumelden.


19

Die Google Play Developers Console bietet Ihnen tatsächlich die Stapelspuren der Apps, die abgestürzt sind und die Berichte gesendet haben. Außerdem enthält sie sehr gute Diagramme, mit denen Sie die Informationen besser anzeigen können (siehe Beispiel unten):

Geben Sie hier die Bildbeschreibung ein


2
Wie lassen Sie die Benutzer die Berichte senden oder wie funktioniert das genau, wenn sich Ihre App nicht im Play Store befindet? Können Sie dies zu Testzwecken tun?
Lion789

Wissen Sie, dass es ein Open-Source-Android-Projekt gibt, das seine Absturzberichte veröffentlicht?
Justin Civi

1
Bitte beachten Sie, dass dies nur die Abstürze
anzeigt

Ja, in der Tat, wenn Sie eine große Benutzerbasis haben, haben Sie viele Möglichkeiten, dass alle Abstürze gemeldet werden, und auch Abstürze und ANRs, die hier gemeldet werden, sind die wichtigsten, da die Leute sie öfter melden, so dass Sie dies können Filtern und beheben Sie sie in dieser Priorität (mehr Berichte = wichtigerer Fehler) während (kein Bericht = nicht dieser kritische Fehler).
Eefret

18

Ich habe Crittercism für meine Android- und iOS-Apps verwendet - habe auf Techcrunch davon gehört. Ziemlich glücklich mit ihnen bisher!


Zu Ihrer Information: Absturzberichte von der NDK-Seite sind nicht Teil des Grundplans und fallen unter "Erweiterte Absturzberichte". Siehe: Crittercism.com/pricing
Ahash

1
Ich habe gerade die NDK-Berichterstattung auf Fabric.io Crashlytics von Twitter getestet ... ziemlich gut (am ersten Tag der Verwendung), es erforderte einen zusätzlichen Schritt, als ich losließ, um das Mapping in ihr System zu integrieren, damit Stapelspuren gut aussehen, aber es hat genagelt Der NDK-Fehler, den ich zum Testen verwendet habe (hat einen "abort ()" - Aufruf strategisch im gesamten c ++ durchgeführt und einen Stack-Trace zum Testen bereitgestellt.
Hunter-Orionnoir


11

Verwenden Sie diese Option, um die Ausnahmedetails abzufangen:

String stackTrace = Log.getStackTraceString(exception); 

Speichern Sie dies in der Datenbank und pflegen Sie das Protokoll.


Wie Sie auf diese Datenbank zugreifen können, geben Sie mir ein Beispiel. bitte wenn du kannst. danke in advacne
Rajendra Verma

8

Sie können dafür auch einen ganzen (einfachen) Dienst verwenden und nicht nur eine Bibliothek. Unsere Firma hat gerade einen Service dafür veröffentlicht: http://apphance.com .

Es verfügt über eine einfache .jar-Bibliothek (für Android), die Sie in 5 Minuten hinzufügen und integrieren können. Anschließend sammelt die Bibliothek nicht nur Absturzinformationen, sondern auch Protokolle von laufenden Anwendungen. Außerdem können Ihre Tester Probleme direkt vom Gerät aus melden - einschließlich der gesamter Kontext (Gerätedrehung, unabhängig davon, ob sie mit einem WLAN verbunden ist oder nicht und mehr). Sie können die Protokolle mithilfe eines sehr schönen und nützlichen Webpanels anzeigen, in dem Sie Sitzungen mit Ihrer Anwendung, Abstürze, Protokolle, Statistiken und mehr verfolgen können. Der Service befindet sich derzeit in der Closed Beta-Testphase, aber Sie können den Zugriff anfordern und wir geben ihn Ihnen sehr schnell.

Haftungsausschluss: Ich bin CTO von Polidea und Mitentwickler des Dienstes.


7

Vielen Dank an die Ressourcen, die Stackoverflowmir dabei helfen, diese Antwort zu finden.

Sie können Ihre Remote-Android-Absturzberichte direkt in Ihrer E-Mail finden . Denken Sie daran, dass Sie Ihre E-Mail-Adresse in die CustomExceptionHandler-Klasse einfügen müssen .

public static String sendErrorLogsTo = "tushar.pandey@virtualxcellence.com" ;

Erforderliche Schritte:

1.) Verwenden Sie in onCreate Ihrer Aktivität diesen Abschnitt Ihres Codes.

    if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
        Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(this));
    }   

2.) Verwenden Sie diese überschriebene Version der CustomExceptionHandler-Klasse von (rrainn) gemäß meinem PHPScript.

package com.vxmobilecomm.activity;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.util.Log;

public class CustomExceptionHandler implements UncaughtExceptionHandler {

    private UncaughtExceptionHandler defaultUEH;
    public static String sendErrorLogsTo = "tushar.pandey@virtualxcellence.com" ;

    Activity activity;

    public CustomExceptionHandler(Activity activity) {
        this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
        this.activity = activity;
    }

    public void uncaughtException(Thread t, Throwable e) {

        final Writer result = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(result);
        e.printStackTrace(printWriter);
        String stacktrace = result.toString();
        printWriter.close();
        String filename = "error" + System.nanoTime() + ".stacktrace";

        Log.e("Hi", "url != null");
        sendToServer(stacktrace, filename);

        StackTraceElement[] arr = e.getStackTrace();
        String report = e.toString() + "\n\n";
        report += "--------- Stack trace ---------\n\n";
        for (int i = 0; i < arr.length; i++) {
            report += "    " + arr[i].toString() + "\n";
        }
        report += "-------------------------------\n\n";

        report += "--------- Cause ---------\n\n";
        Throwable cause = e.getCause();
        if (cause != null) {
            report += cause.toString() + "\n\n";
            arr = cause.getStackTrace();
            for (int i = 0; i < arr.length; i++) {
                report += "    " + arr[i].toString() + "\n";
            }
        }
        report += "-------------------------------\n\n";

        defaultUEH.uncaughtException(t, e);
    }

    private void sendToServer(String stacktrace, String filename) {
        AsyncTaskClass async = new AsyncTaskClass(stacktrace, filename,
                getAppLable(activity));
        async.execute("");
    }

    public String getAppLable(Context pContext) {
        PackageManager lPackageManager = pContext.getPackageManager();
        ApplicationInfo lApplicationInfo = null;
        try {
            lApplicationInfo = lPackageManager.getApplicationInfo(
                    pContext.getApplicationInfo().packageName, 0);
        } catch (final NameNotFoundException e) {
        }
        return (String) (lApplicationInfo != null ? lPackageManager
                .getApplicationLabel(lApplicationInfo) : "Unknown");
    }

    public class AsyncTaskClass extends AsyncTask<String, String, InputStream> {
        InputStream is = null;
        String stacktrace;
        final String filename;
        String applicationName;

        AsyncTaskClass(final String stacktrace, final String filename,
                String applicationName) {
            this.applicationName = applicationName;
            this.stacktrace = stacktrace;
            this.filename = filename;
        }

        @Override
        protected InputStream doInBackground(String... params) 
        { 
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(
                    "http://suo-yang.com/books/sendErrorLog/sendErrorLogs.php?");

            Log.i("Error", stacktrace);

            try {
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
                        6);

                nameValuePairs.add(new BasicNameValuePair("data", stacktrace));
                nameValuePairs.add(new BasicNameValuePair("to",sendErrorLogsTo));
                nameValuePairs.add(new BasicNameValuePair("subject",applicationName));

                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

                HttpResponse response = httpclient.execute(httppost);

                HttpEntity entity1 = response.getEntity();

                BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(
                        entity1);

                is = bufHttpEntity.getContent();

            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return is;
        }

        @Override
        protected void onPostExecute(InputStream result) {
            super.onPostExecute(result);

            Log.e("Stream Data", getStringFromInputStream(is));
        }
    }

    // convert InputStream to String
    private static String getStringFromInputStream(InputStream is) {

        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();

        String line;
        try {

            br = new BufferedReader(new InputStreamReader(is));
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return sb.toString();

    }
}


5

Dies ist sehr brutal, aber es ist möglich, Logcat überall auszuführen, sodass ein schneller und schmutziger Hack zu jedem Catch-Block hinzugefügt werden kann getRuntime().exec("logcat >> /sdcard/logcat.log");


Dies würde die Protokollausgabe aller Apps ergeben. Das Filtern nach dem App-Tag-Namen ist möglicherweise in Ordnung, aber denken Sie nicht, dass dies ein guter Weg wäre, da die Einträge möglicherweise kumulativ sind. Das Löschen der Logcat-Ausgabe nach jedem Schreibvorgang kann dieses Problem jedoch beheben.
Bschandramohan

5

Es gibt ein Tool namens Fabric. Hierbei handelt es sich um ein Crash-Analyse-Tool, mit dem Sie Crash-Berichte abrufen können, wenn die Anwendung live und während der Entwicklung bereitgestellt wird. Das Hinzufügen dieses Tools zu Ihrer Anwendung war ebenfalls einfach. Wenn Ihre Anwendung abstürzt, kann dieser Bericht über den Absturz in Ihrem Fabric.io-Dashboard angezeigt werden. Der Bericht wurde automatisch abgefangen. Der Benutzer wird nicht um Erlaubnis gebeten. Ob er / sie den Fehler- / Absturzbericht senden möchte. Und das ist völlig kostenlos ... https://get.fabric.io/


5

Google Firebase ist die neueste Methode von Google (2016), mit der Sie Absturz- / Fehlerdaten auf Ihrem Telefon bereitstellen können. Fügen Sie es in Ihre build.gradle-Datei ein:

compile 'com.google.firebase:firebase-crash:9.0.0'

Schwerwiegende Abstürze werden automatisch protokolliert, ohne dass Benutzereingaben erforderlich sind. Sie können auch nicht schwerwiegende Abstürze oder andere Ereignisse wie die folgenden protokollieren:

try
{

}
catch(Exception ex)
{
    FirebaseCrash.report(new Exception(ex.toString()));
}

5

Es gibt diese Android-Bibliothek namens Sherlock . Sie erhalten den vollständigen Absturzbericht sowie Informationen zu Geräten und Anwendungen. Bei jedem Absturz wird eine Benachrichtigung in der Benachrichtigungsleiste angezeigt. Beim Klicken auf die Benachrichtigung werden die Absturzdetails geöffnet. Sie können Absturzdetails auch per E-Mail oder über andere Freigabeoptionen mit anderen teilen.

Installation

android {
    dataBinding {
      enabled = true
    }
}

compile('com.github.ajitsing:sherlock:1.0.0@aar') {
    transitive = true
}

Demo

Geben Sie hier die Bildbeschreibung ein


5

Während viele der Antworten auf dieser Seite nützlich sind, können sie leicht veraltet sein. Auf der AppBrain-Website werden Statistiken zusammengefasst, mit denen Sie die beliebteste aktuelle Crash-Reporting-Lösung finden können:

Bibliotheken für Android-Absturzberichte

App Gehirn Website

Sie können sehen, dass Crashlytics zum Zeitpunkt der Veröffentlichung dieses Bildes in 5,24% der Apps und 12,38% der Installationen verwendet wird.


4

Wir verwenden unser selbst entwickeltes System innerhalb des Unternehmens und es dient uns sehr gut. Es ist eine Android-Bibliothek, die Absturzberichte an Server sendet und Server, die Berichte empfangen und einige Analysen durchführen. Der Server gruppiert Ausnahmen nach Ausnahmenname, Stacktrace und Nachricht. Es hilft, die kritischsten Probleme zu identifizieren, die behoben werden müssen. Unser Service befindet sich jetzt in der öffentlichen Beta, sodass jeder es ausprobieren kann. Sie können ein Konto unter http://watchcat.co erstellen oder einfach einen Blick darauf werfen, wie es mit dem Demo-Zugriff http://watchcat.co/reports/index.php?demo funktioniert .


3

Wenn Sie sofort Antworten wünschen, können Sie logcat verwenden

$adb shell logcat -f /sdcard/logoutput.txt *:E

Wenn sich gerade zu viel Müll in Ihrem Protokoll befindet, löschen Sie ihn zuerst.

$adb shell logcat -c

Führen Sie dann Ihre App aus und logcat erneut.


Erfordert dies nicht immer noch, dass Sie das Gerät an einen PC anschließen (z. B. mit einem Kabel)?
Gerard

3

Ich habe eine weitere großartige Webanwendung gefunden, um die Fehlerberichte zu verfolgen.

https://mint.splunk.com/

Kleine Anzahl zu konfigurierender Schritte.

  1. Melden Sie sich an oder melden Sie sich an und konfigurieren Sie über den obigen Link. Sobald Sie eine Anwendung erstellt haben, wird eine Zeile zum Konfigurieren wie unten angegeben bereitgestellt.
Mint.initAndStartSession(YourActivity.this, "api_key");
  1. Fügen Sie Folgendes in die build.gradl der Anwendung ein.
android {
...
    repositories {
        maven { url "https://mint.splunk.com/gradle/"}
    }
...
}

dependencies {
...
    compile "com.splunk.mint:mint:4.4.0"
...
}
  1. Fügen Sie den oben kopierten Code hinzu und fügen Sie ihn jeder Aktivität hinzu.

    Mint.initAndStartSession (YourActivity.this, "api_key");

Das ist es. Wenn Sie sich anmelden und zu Ihrem Anwendungs-Dashboard gehen, erhalten Sie alle Fehlerberichte.

Hoffe es hilft jemandem.


Wieviel kostet das?
user2966445

2

Für einen alternativen Crash-Reporting- / Exception-Tracking-Service besuchen Sie Raygun.io - es enthält eine Reihe netter Logik für die Behandlung von Android-Crashs, einschließlich einer anständigen Benutzererfahrung beim Einstecken in Ihre App (zwei Codezeilen in Ihrer Hauptaktivität und einige wenige) in AndroidManifest eingefügte XML-Zeilen).

Wenn Ihre App abstürzt, werden automatisch der Stack-Trace, Umgebungsdaten für Hard / Software, Benutzer-Tracking-Informationen, von Ihnen angegebene benutzerdefinierte Daten usw. abgerufen. Sie werden asynchron an die API gesendet, sodass der UI-Thread nicht blockiert wird, und zwischengespeichert auf die Festplatte, wenn kein Netzwerk verfügbar ist.

Haftungsausschluss: Ich habe den Android-Anbieter erstellt :)


1

Ich habe gerade angefangen, ACRA https://github.com/ACRA/acra mit Google Forms als Backend zu verwenden. Die Einrichtung und Verwendung ist sehr einfach. Dies ist die Standardeinstellung.

ABER das Senden von Berichten an Google Forms wird veraltet (und dann entfernt): https://plus.google.com/118444843928759726538/posts/GTTgsrEQdN6 https://github.com/ACRA/acra/wiki/Notice-on-Google -Form-Spreadsheet-Verwendung

Auf jeden Fall ist es möglich , eigenen Absender zu definieren https://github.com/ACRA/acra/wiki/AdvancedUsage#wiki-Implementing_your_own_sender Sie einen Versuch , um E - Mail - Absender zum Beispiel geben können.

Mit minimalem Aufwand ist es möglich, Berichte an bugsense zu senden: http://www.bugsense.com/docs/android#acra

NB Das kostenlose Bugsense-Konto ist auf 500 Berichte / Monat begrenzt


1

Spät zur Party unterstütze und glaube ich, dass ACRA die beste Option unter allen ist. Es ist einfach einzurichten und zu konfigurieren. Ich habe eine detaillierte Anleitung mit Eingaben aus aller Welt erstellt, um den Absturzbericht mit ACRA abzurufen und mit MandrillAp an meine E-Mail-Adresse zu senden.

Link zum Beitrag: https://androidician.wordpress.com/2015/03/29/sending-crash-reports-with-acra-over-email-using-mandrill/

Link zum Beispielprojekt auf github: https://github.com/ayushhgoyal/AcraSample


1

Ich bin einer der Gründer von Bugsnag, das wir genau für diesen Zweck entwickelt haben. Bugsnag erfasst automatisch nicht behandelte Ausnahmen in Android-Apps und sendet sie an unser Dashboard, wo Sie Korrekturen priorisieren und in Diagnoseinformationen eintauchen können.

Bei der Auswahl oder Erstellung eines Absturzmeldesystems sind einige wichtige Punkte zu beachten, zusammen mit einigen Codefragmenten:

  • Erkennt nicht behandelte Ausnahmen automatisch ( Beispielcode )
  • Sammelt Diagnosedaten wie Speichernutzung, Geräteinformationen usw. ( Beispielcode )
  • Effektiv gruppieren Gruppen Abstürze nach Grundursache
  • Ermöglicht das Verfolgen von Aktionen, die der Benutzer vor jedem Absturz ausgeführt hat, um die Reproduktion zu erleichtern ( Beispielcode )

Wenn Sie einige bewährte Methoden zur Behandlung / Berichterstellung von Unfällen unter Android kennenlernen möchten, können Sie den vollständigen Quellcode für die vollständig Open Source- Bibliothek für Absturzberichte von Bugsnag lesen. Sie können diese auch zerreißen und in Ihren eigenen Anwendungen verwenden!


0

Wenn Ihre App von anderen Personen heruntergeladen wird und auf Remote-Geräten abstürzt, sollten Sie sich eine Android-Fehlerberichtsbibliothek ansehen (auf die in diesem SO-Beitrag verwiesen wird ). Wenn es sich nur um Ihr eigenes lokales Gerät handelt, können Sie LogCat verwenden. Selbst wenn das Gerät zum Zeitpunkt des Absturzes nicht mit einem Host-Computer verbunden war, wird durch Anschließen des Geräts und Ausgeben eines Befehls adb logcat der gesamte Logcat-Verlauf heruntergeladen (zumindest in dem Maße, in dem er gepuffert ist, was normalerweise eine Menge Protokolldaten darstellt , es ist einfach nicht unendlich). Beantworten eine dieser Optionen Ihre Frage? Wenn nicht, können Sie versuchen zu klären, wonach Sie ein bisschen mehr suchen?



0

Google hat geändert, wie viele Absturzberichte Sie tatsächlich erhalten. Bisher haben Sie nur manuell gemeldete Fehlerberichte erhalten.

Seit der letzten Entwicklerkonferenz und der Einführung von Android Vitals erhalten Sie auch Absturzberichte von Benutzern, die den Austausch von Diagnosedaten ermöglicht haben.

Sie sehen alle Abstürze von Android-Geräten, deren Benutzer sich für die automatische Freigabe von Nutzungs- und Diagnosedaten entschieden haben. Daten sind für die letzten zwei Monate verfügbar.

Anzeigen von Abstürzen und ANR-Fehlern (Application reagiert nicht)


logcat sagt, dass es in /data/user/0/com eine Ausgabe-Crash-Dump-Datei gibt. <myappname>/cache/WebView/Crash Report / <GUUID> .dmp, aber das Gerät ist nicht gerootet und ich kann es nicht herausfinden wie man auf diese Datei zugreift!
Michael

0

Sie können dies direkt in Android Studio tun. Schließen Sie einfach Ihr Telefon an, führen Sie die App aus, lassen Sie sie abstürzen und Sie können den Stacktrace direkt in Android Studio anzeigen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.