Question Comment puis-je obtenir des données de crash à partir de mon application Android?


Comment puis-je obtenir des données d'accident (traces de pile au moins) de mon application Android? Au moins lorsque je travaille sur mon propre appareil étant récupéré par câble, mais idéalement à partir de n'importe quelle instance de mon application fonctionnant sur la nature afin que je puisse l'améliorer et le rendre plus solide.


684
2018-05-18 08:52


origine


Réponses:


Vous pourriez essayer le ACRA (Application Crash Report pour Android) bibliothèque:

ACRA est une bibliothèque permettant à l'application Android de publier automatiquement ses rapports d'erreur dans un formulaire GoogleDoc. Il est destiné aux développeurs d'applications Android pour les aider à obtenir des données de leurs applications lorsqu'ils se plantent ou se comportent de manière erronée.

Il est facile à installer dans votre application, hautement configurable et ne vous oblige pas à héberger un script serveur n'importe où ... les rapports sont envoyés à une feuille de calcul Google Doc!


341
2018-04-16 08:00



Pour des exemples d'applications et de débogage, j'utilise une solution simple qui me permet d'écrire la pile sur la carte SD de l'appareil et / ou de la télécharger sur un serveur. Cette solution a été inspirée par Project android-remote-stacktrace (en particulier, les pièces save-to-device et upload-to-server) et je pense que cela résout le problème mentionné par Soonil. Ce n'est pas optimal, mais cela fonctionne et vous pouvez l'améliorer si vous voulez l'utiliser dans une application de production. Si vous décidez de télécharger les stacktraces sur le serveur, vous pouvez utiliser un script php (index.php) pour les voir. Si vous êtes intéressé, vous pouvez trouver toutes les sources ci-dessous - une classe java pour votre application et deux scripts php optionnels pour le serveur hébergeant les stacktraces téléchargés.

Dans un contexte (par exemple, l'activité principale), appelez

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

283
2018-05-28 10:34



Vous pouvez aussi essayer BugSense. BugSense recueille et analyse tous les rapports d'erreur et vous donne des rapports significatifs et visuels. C'est gratuit et c'est seulement 1 ligne de code pour s'intégrer.

Disclaimer: Je suis un co-fondateur


54
2018-03-18 17:24



Dans Android 2.2, il est désormais possible d'obtenir automatiquement des rapports d'erreur à partir des applications Android Market:

Nouvelle fonctionnalité de rapport de bogue pour Android   Les applications de marché permettent aux développeurs de   recevoir des rapports d'erreur et de blocage de   leurs utilisateurs. Les rapports seront   disponible quand ils se connectent à leur   compte d'éditeur.

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


42
2018-05-13 21:51



Il est possible de gérer ces exceptions avec Thread.setDefaultUncaughtExceptionHandler(), mais cela semble déranger avec la méthode de gestion des exceptions d'Android. J'ai essayé d'utiliser un gestionnaire de cette nature:

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

Cependant, même avec la reprise des exceptions, je n'ai pas réussi à obtenir le comportement souhaité, c'est-à-dire consigner l'exception tout en permettant à Android d'éteindre le composant qui lui était arrivé, j'ai donc abandonné après un certain temps.


24
2017-12-15 00:25



Ok, bien, j'ai regardé les échantillons fournis par rrainn et Soonil, et j'ai trouvé une solution cela ne gâche pas la gestion des erreurs.

J'ai modifié le CustomExceptionHandler afin qu'il stocke le UncaughtExceptionHandler d'origine du Thread auquel nous associons le nouveau. À la fin de la nouvelle "uncaughtException" - Méthode Je viens d'appeler l'ancienne fonction en utilisant le UncaughtExceptionHandler stocké.

Dans la classe DefaultExceptionHandler, vous avez besoin de sth. comme ça:

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

Avec cette modification sur le code à http://code.google.com/p/android-remote-stacktrace vous avez une bonne base de travail pour vous connecter sur le terrain à votre serveur web ou carte SD.


19
2017-08-02 07:47



J'ai utilisé Crittercisme pour mes applications Android et iOS - entendu parler d'eux sur techcrunch. Assez content avec eux jusqu'à présent!


18