Вы также можете использовать класс 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))); }
Возможно обработать эти исключения с 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 завершить работу компонента, это произошло он, таким образом, я разочаровался в нем через некоторое время.
Для примеров приложений и в целях отладки я использую простое решение, которое позволяет мне записывать трассировку стека на карту 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");
?>
Хорошо, я просмотрел предоставленные образцы от 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-карта.
I made my own version here : http://androidblogger.blogspot.com/2009/12/how-to-improve-your-application-crash.html
Это в основном то же самое, но я использую почту, а не http соединение для отправки отчета, и, что более важно, я добавил в свой отчет некоторую информацию, такую как версия приложения, версия ОС, модель телефона или доступная память ...
Вы можете попробовать ACRA (Application Crash Report for Android) библиотеку:
ACRA - это библиотека, позволяющая Android-приложениям автоматически публиковать свои отчеты об авариях в форме GoogleDoc. Она предназначена для разработчиков приложений для Android, чтобы помочь им получить данные от своих приложений, когда они аварийно завершаются или ведут себя неправильно.
Его легко установить в ваше приложение, он хорошо настраивается и не требует размещения серверного скрипта где-либо... отчеты отправляются в электронную таблицу Google Doc!
В Android 2.2 теперь можно автоматически получать отчеты о сбоях из приложений Android Market:
Новая функция отчетов об ошибках для Android Приложения из Market позволяют разработчикам получать отчеты о сбоях и зависаниях от их пользователи. Отчеты будут доступны, когда они входят в свой аккаунт издателя.
http://developer.android.com/sdk/android-2.2-highlights.html