Как получить данные о сбое из моего приложения Android? - PullRequest
712 голосов
/ 02 марта 2009

Как я могу получить данные о сбоях (по крайней мере, следы стека) из моего приложения для Android? По крайней мере, при работе с моим собственным устройством, полученным по кабелю, но в идеале из любого экземпляра моего приложения, работающего на дикой природе, чтобы я мог улучшить его и сделать его более надежным.

Ответы [ 30 ]

345 голосов
/ 18 мая 2010

Вы можете попробовать ACRA (Отчет о сбое приложения для Android) библиотека:

ACRA - это библиотека, позволяющая Android-приложению автоматически публиковать свои отчеты о сбоях в форме GoogleDoc. Он предназначен для разработчиков приложений для Android, чтобы помочь им получать данные из своих приложений в случае сбоя или неправильного поведения.

Его легко установить в приложении, он легко настраивается и не требует размещения серверного скрипта где-либо ... отчеты отправляются в таблицу Google Doc!

294 голосов
/ 16 апреля 2009

В примерах приложений и в целях отладки я использую простое решение, которое позволяет мне записывать трассировку стека на SD-карту устройства и / или загружать ее на сервер. Это решение было вдохновлено Project android-remote-stacktrace (в частности, части для сохранения на устройство и загрузки на сервер), и я думаю, что оно решает проблему, упомянутую Soonil. Это не оптимально, но работает, и вы можете улучшить его, если хотите использовать его в производственном приложении. Если вы решили загрузить трассировки стека на сервер, вы можете использовать php-скрипт (index.php) для их просмотра. Если вам интересно, вы можете найти все источники ниже - один java-класс для вашего приложения и два необязательных php-скрипта для сервера, на котором размещены загруженные стековые трассы.

В контексте (например, основной вид деятельности), позвоните

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");
?>
54 голосов
/ 08 июля 2011

Вы также можете попробовать BugSense . BugSense собирает и анализирует все отчеты о сбоях и дает вам значимые и визуальные отчеты. Это бесплатно и это только 1 строка кода для интеграции.

Отказ от ответственности: я соучредитель

42 голосов
/ 28 мая 2010

В Android 2.2 теперь можно автоматически получать отчеты о сбоях из приложений Android Market:

Новая функция отчетов об ошибках для Android Рынок приложений позволяет разработчикам получать отчеты о сбоях и зависаниях от их пользователи. Отчеты будут доступны, когда они входят в их аккаунт издателя.

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

25 голосов
/ 18 марта 2009

Возможно обработать эти исключения с помощью Thread.setDefaultUncaughtExceptionHandler(), однако это, похоже, мешает Android-методу обработки исключений. Я попытался использовать такой обработчик:

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

Однако даже после переброса исключений мне не удалось получить желаемое поведение, то есть записать исключение, в то же время позволяя Android завершить работу компонента, в котором это произошло, поэтому через некоторое время я разочаровался.

20 голосов
/ 27 июня 2013

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

Дайте Crashlytics попробовать. Он позволит лучше понять все сбои на всех устройствах, на которых установлено ваше приложение, и отправит вам уведомление по электронной почте. И самое приятное, что он полностью бесплатный.

20 голосов
/ 14 мая 2009

Хорошо, я посмотрел предоставленные образцы от Rrainn и Soonil и нашел решение. это не мешает обработке ошибок.

Я изменил CustomExceptionHandler, чтобы он сохранял исходный UncaughtExceptionHandler из потока, с которым мы связываем новый. В конце нового «uncaughtException» - Метод Я просто вызываю старую функцию, используя сохраненный UncaughtExceptionHandler.

В классе DefaultExceptionHandler вам нужен sth. как это:

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

С этой модификацией кода на http://code.google.com/p/android-remote-stacktrace у вас есть хорошая рабочая база для входа в поле на ваш веб-сервер или сд-карта.

18 голосов
/ 07 мая 2015

Консоль разработчиков Google Play фактически дает вам трассировку стека от тех приложений, которые потерпели крах и отправили отчеты, а также имеет очень хорошие диаграммы, чтобы помочь вам увидеть информацию, см. Пример ниже:

enter image description here

18 голосов
/ 03 октября 2011

Я использовал Crittercism для своих приложений для Android и iOS - слышал о них на techcrunch. Очень доволен ими до сих пор!

14 голосов
/ 15 декабря 2009

Я сделал свою версию здесь: http://androidblogger.blogspot.com/2009/12/how-to-improve-your-application-crash.html

Это в основном то же самое, но я использую почту, а не http-связь для отправки отчета, и, что более важно, я добавил в свою информацию некоторые данные, такие как версия приложения, версия ОС, модель телефона или доступная память отчет ...

...