Как получить данные о сбое из моего приложения Android?

Вы также можете использовать класс TimeUnit . Вы можете определить, что

private static final String FORMAT = "%02d:%02d:%02d";

может иметь такой метод, как:

public static String parseTime(long milliseconds) {
      return String.format(FORMAT,
              TimeUnit.MILLISECONDS.toHours(milliseconds),
              TimeUnit.MILLISECONDS.toMinutes(milliseconds) - TimeUnit.HOURS.toMinutes(
              TimeUnit.MILLISECONDS.toHours(milliseconds)),
              TimeUnit.MILLISECONDS.toSeconds(milliseconds) - TimeUnit.MINUTES.toSeconds(
              TimeUnit.MILLISECONDS.toMinutes(milliseconds)));
   }

721
задан 2 revs 1 October 2010 в 09:13
поделиться

6 ответов

Возможно обработать эти исключения с 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 завершить работу компонента, это произошло он, таким образом, я разочаровался в нем через некоторое время.

28
ответ дан blackpanther 1 October 2010 в 20:13
поделиться
  • 1
    Вид поражений точка для игнорирования того требования. – Jeff 12 August 2009 в 08:58

Для примеров приложений и в целях отладки я использую простое решение, которое позволяет мне записывать трассировку стека на карту 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");
?>
297
ответ дан 22 November 2019 в 21:31
поделиться

Хорошо, я просмотрел предоставленные образцы от 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 у вас есть хорошая рабочая база для входа в поле на свой веб-сервер или SD-карта.

20
ответ дан 22 November 2019 в 21:31
поделиться

I made my own version here : http://androidblogger.blogspot.com/2009/12/how-to-improve-your-application-crash.html

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

14
ответ дан 22 November 2019 в 21:31
поделиться

Вы можете попробовать ACRA (Application Crash Report for Android) библиотеку:

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

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

349
ответ дан 22 November 2019 в 21:31
поделиться

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

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

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

43
ответ дан 22 November 2019 в 21:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: