restringir - ¿Cómo obtengo datos erróneos de mi aplicación de Android?
twitter no funciona 2018 (30)
¿Cómo puedo obtener datos de fallos (al menos trazas de pila) desde mi aplicación de Android? Al menos cuando trabajo en mi propio dispositivo, se recupera por cable, pero idealmente desde cualquier instancia de mi aplicación que se ejecute de forma salvaje para poder mejorarla y hacerla más sólida.
Acaba de empezar a usar ACRA https://github.com/ACRA/acra usando Google Forms como backend y es muy fácil de configurar y usar, es el valor predeterminado.
PERO El envío de informes a los formularios de Google quedará en desuso (se eliminará): https://plus.google.com/118444843928759726538/posts/GTTgsrEQdN6 https://github.com/ACRA/acra/wiki/Notice-on-Google-Form-Spreadsheet-usage
De todos modos, es posible definir su propio remitente https://github.com/ACRA/acra/wiki/AdvancedUsage#wiki-Implementing_your_own_sender . Puede intentar enviar un correo electrónico al remitente, por ejemplo.
Con el mínimo esfuerzo es posible enviar informes a bugsense: http://www.bugsense.com/docs/android#acra
NB La cuenta gratuita de bugsense está limitada a 500 informes / mes
Bien, miré las muestras provistas por Rrainn y Soonil, y encontré una solución que no estropea el manejo de errores.
Modifiqué el CustomExceptionHandler para que almacene el UncaughtExceptionHandler original del Thread al que asociamos el nuevo. Al final de la nueva "UncaughtException": método que acabo de llamar a la función antigua utilizando el UncaughtExceptionHandler almacenado.
En la clase DefaultExceptionHandler necesitas algo. Me gusta esto:
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();
}
}
Con esa modificación en el código en http://code.google.com/p/android-remote-stacktrace , tiene una buena base de trabajo para iniciar sesión en el campo en su servidor web o en una tarjeta SD.
Después de la fiesta, apoyo y creo que ACRA es la mejor opción entre todas. Es fácil de configurar y configurar. He creado una guía detallada con entradas de todo el mundo para obtener el informe de fallos usando ACRA y enviarlo por correo a mi dirección de correo electrónico usando MandrillAp.
Enlace a la publicación: https://androidician.wordpress.com/2015/03/29/sending-crash-reports-with-acra-over-email-using-mandrill/
Enlace al proyecto de muestra en github: https://github.com/ayushhgoyal/AcraSample
En Android 2.2 ahora es posible obtener automáticamente informes de bloqueos desde aplicaciones de Android Market:
La nueva función de informe de errores para aplicaciones de Android Market permite a los desarrolladores recibir informes de bloqueo y congelación de sus usuarios. Los informes estarán disponibles cuando inicien sesión en su cuenta de editor.
http://developer.android.com/sdk/android-2.2-highlights.html
Encontré una aplicación web genial para rastrear los informes de errores.
Pequeño número de pasos para configurar.
- Inicie sesión o regístrese y configure utilizando el enlace anterior. Una vez que haya terminado de crear una aplicación, proporcionarán una línea para configurar como se muestra a continuación.
Mint.initAndStartSession(YourActivity.this, "api_key");
- Agregue lo siguiente en el build.gradl de la aplicación.
android { ... repositories { maven { url "https://mint.splunk.com/gradle/"} } ... } dependencies { ... compile "com.splunk.mint:mint:4.4.0" ... }
- Agregue el código que copiamos arriba y agréguelo a cada actividad.
Mint.initAndStartSession (YourActivity.this, "api_key");
Eso es. Al iniciar sesión y acceder al panel de su aplicación, obtendrá todos los informes de errores.
Espero que ayude a alguien.
Es posible manejar estas excepciones con Thread.setDefaultUncaughtExceptionHandler()
, sin embargo, esto parece Thread.setDefaultUncaughtExceptionHandler()
el método de manejo de excepciones de Android. Intenté usar un controlador de esta naturaleza:
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");
}
}
Sin embargo, incluso con el reenvío de las excepciones, no pude obtener el comportamiento deseado, es decir, registrar la excepción y al mismo tiempo permitir que Android apague el componente que lo había sucedido, por lo que me di por vencido al cabo de un tiempo.
Esto es muy brutal, pero es posible ejecutar logcat en cualquier lugar, por lo que un hack rápido y sucio es agregar a cualquier bloque catch getRuntime().exec("logcat >> /sdcard/logcat.log");
Existe una herramienta llamada tejido, esta es una herramienta analítica de fallos, que le permitirá obtener informes de fallos cuando la aplicación se implementa en vivo y durante el desarrollo. Agregar esta herramienta a su aplicación también fue simple. Cuando su aplicación falla, se puede ver el informe de la falla desde el panel de Fabric.io. El informe se detectó automáticamente. No le pedirá permiso al usuario. Si él / ella quiere enviar el informe de error / accidente. Y esto es completamente gratis ... https://get.fabric.io/
Google cambió la cantidad de informes de fallos que realmente obtienes. Anteriormente solo recibías informes de errores informados manualmente.
Desde la última conferencia de desarrolladores y la introducción de Android Vitals , también recibe informes de fallos de usuarios que han permitido compartir datos de diagnóstico.
Verá todos los bloqueos recopilados desde dispositivos Android cuyos usuarios han optado por compartir automáticamente los datos de uso y diagnóstico. Los datos están disponibles para los dos meses anteriores.
Gracias a los recursos presentes en me ayudaron a encontrar esta respuesta.
Puede encontrar sus informes de errores remotos de Android directamente en su correo electrónico . recuerde que debe poner su correo electrónico dentro de la clase CustomExceptionHandler .
public static String sendErrorLogsTo = "[email protected]" ;
Pasos requeridos:
1º) en onCreate de su actividad use esta sección de su código.
if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(this));
}
2º) use esta versión anulada de la clase CustomExceptionHandler de (rrainn), de acuerdo con mi 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 = "[email protected]" ;
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();
}
}
Hay esta biblioteca de android llamada Sherlock . Le proporciona el informe completo de la falla junto con la información del dispositivo y la aplicación. Cada vez que se produce un bloqueo, muestra una notificación en la barra de notificaciones y al hacer clic en la notificación, abre los detalles del bloqueo. También puede compartir los detalles del accidente con otras personas por correo electrónico u otras opciones para compartir.
Instalación
android {
dataBinding {
enabled = true
}
}
compile(''com.github.ajitsing:sherlock:1.0.0@aar'') {
transitive = true
}
Manifestación
He estado usando Crittercism para mis aplicaciones de Android e iOS, escuché sobre ellas en techcrunch. Muy feliz con ellos hasta ahora!
Hice mi propia versión aquí: http://androidblogger.blogspot.com/2009/12/how-to-improve-your-application-crash.html
Básicamente es lo mismo, pero estoy usando un correo en lugar de una conexión http para enviar el informe y, lo que es más importante, agregué información a mi informe como la versión de la aplicación, la versión del sistema operativo, el modelo del teléfono o la memoria disponible. .
Hoy en día, los informes de Firebase Crash son muy populares y fáciles de usar. Consulte el siguiente enlace para obtener más información: Firebase Crash Reporting
Espero que te ayude.
La Consola de desarrolladores de Google Play en realidad le brinda los seguimientos de la pila de aquellas aplicaciones que se bloquearon y enviaron los informes, también tiene muy buenos gráficos para ayudarlo a ver la información, consulte el siguiente ejemplo:
Para un servicio alternativo de informe de Raygun.io / seguimiento de excepciones, visite Raygun.io : tiene una buena lógica para manejar los fallos de Android, incluida una experiencia de usuario decente al conectarla a su aplicación (dos líneas de código en su actividad principal y algunas líneas de XML pegadas en AndroidManifest).
Cuando su aplicación falla, automáticamente tomará el seguimiento de la pila, los datos del entorno para hardware / software, la información de seguimiento del usuario, cualquier información personalizada que especifique, etc. La publica en la API de forma asíncrona, por lo que no se bloquea el subproceso de la interfaz de usuario, y la almacena en caché a disco si no hay red disponible.
Descargo de responsabilidad: construí el proveedor de Android :)
Puede probar la biblioteca ACRA (Informe de bloqueo de aplicaciones para Android) :
ACRA es una biblioteca que permite que la aplicación de Android publique automáticamente sus informes de fallos en un formulario de GoogleDoc. Está dirigido a los desarrolladores de aplicaciones de Android para ayudarles a obtener datos de sus aplicaciones cuando se bloquean o se comportan erróneamente.
Es fácil de instalar en su aplicación, es altamente configurable y no requiere que guarde un script de servidor en ningún lugar ... ¡los informes se envían a una hoja de cálculo de Google Doc!
Puedes hacerlo directamente en Android Studio. Solo conecta tu teléfono, ejecuta la aplicación, deja que se bloquee y podrás ver el seguimiento de pila directamente en Android Studio.
Si bien muchas de las respuestas en esta página son útiles, es fácil que estén desactualizadas. El sitio web de AppBrain agrega estadísticas que le permiten encontrar la solución de informes de fallos más popular actual:
Bibliotecas de informes de errores de Android
Puede ver que en el momento de publicar esta imagen, Crashlytics se utiliza en el 5.24% de las aplicaciones y el 12.38% de las instalaciones.
Si otras personas descargan su aplicación y se bloquean en dispositivos remotos, es posible que desee consultar una biblioteca de informes de errores de Android (a la que se hace referencia en esta publicación SO ). Si solo está en su propio dispositivo local, puede usar LogCat. Incluso si el dispositivo no estaba conectado a una máquina host cuando se produjo el bloqueo, conectó el dispositivo y emitió un comando adb logcat para descargar el historial completo de logcat (al menos en la medida en que esté almacenado en el búfer, que generalmente es una gran cantidad de datos de registro , simplemente no es infinito). ¿Alguna de estas opciones responde a tu pregunta? Si no, ¿puedes intentar aclarar lo que estás buscando un poco más?
Si quieres respuestas inmediatamente puedes usar logcat
$adb shell logcat -f /sdcard/logoutput.txt *:E
Si hay demasiada basura en tu registro en este momento, intenta eliminarlo primero.
$adb shell logcat -c
A continuación, intente ejecutar su aplicación y logcat nuevamente.
Soy uno de los fundadores de Bugsnag que diseñamos para este propósito. Bugsnag captura automáticamente las excepciones no controladas en las aplicaciones de Android y las envía a nuestro panel de control, donde puede priorizar las correcciones y sumergirse en la información de diagnóstico.
Aquí hay algunas cosas importantes que se deben tener en cuenta al seleccionar o crear un sistema de informes de fallos, junto con algunos fragmentos de código:
- Detecta excepciones no manejadas automáticamente ( código de ejemplo )
- Recopila datos de diagnóstico, como el uso de la memoria, la información del dispositivo, etc. ( código de ejemplo )
- Agrupa efectivamente los choques por causa raíz.
- Le permite realizar un seguimiento de las acciones que el usuario tomó antes de cada bloqueo para ayudar a reproducir ( código de ejemplo )
Si desea ver algunas de las mejores prácticas sobre manejo / reporte de fallas en Android, puede consultar el código fuente completo de la biblioteca de reporte de fallas de Bugsnag, que es totalmente de código abierto, ¡siéntase libre de separar esto y usarlo en sus propias aplicaciones!
También puede usar un servicio completo (simple) para él en lugar de solo una biblioteca. Nuestra compañía acaba de lanzar un servicio solo para eso: http://apphance.com .
Tiene una biblioteca simple .jar (para Android) que agrega e integra en 5 minutos y luego la biblioteca no solo recopila información de fallos, sino que también registra los registros de la aplicación en ejecución, y permite que los evaluadores informen los problemas directamente desde el dispositivo, incluido el Todo el contexto (rotación del dispositivo, ya sea que esté conectado a un wifi o no y más). Puede mirar los registros utilizando un panel web muy agradable y útil, donde puede realizar un seguimiento de las sesiones con su aplicación, bloqueos, registros, estadísticas y más. El servicio está en fase de prueba beta cerrada ahora, pero puede solicitar acceso y se lo entregamos muy rápidamente.
Descargo de responsabilidad: Soy CTO de Polidea y co-creador del servicio.
También puedes probar BugSense . BugSense recopila y analiza todos los informes de fallos y le proporciona informes significativos y visuales. Es gratis y solo tiene 1 línea de código para poder integrarlo.
Descargo de responsabilidad: soy co-fundador
Use esto para capturar los detalles de la excepción:
String stackTrace = Log.getStackTraceString(exception);
almacenar esto en la base de datos y mantener el registro.
Utilizamos nuestro sistema propio dentro de la empresa y nos sirve muy bien. Es una biblioteca de Android que envía informes de fallos al servidor y al servidor que recibe informes y realiza algunos análisis. El servidor agrupa las excepciones por nombre de excepción, stacktrace, mensaje. Ayuda a identificar la mayoría de los problemas críticos que deben solucionarse. Nuestro servicio está en beta pública ahora para que todos puedan probarlo. Puede crear una cuenta en http://watchcat.co o simplemente echar un vistazo a cómo funciona con el acceso de demostración http://watchcat.co/reports/index.php?demo .
Veo que la pregunta es demasiado antigua y espero que mi respuesta sea útil para otros que tienen el mismo problema ...
Dale una oportunidad a Crashlytics . Brindará una visión detallada de todos los fallos en todos los dispositivos que tienen su aplicación y le enviará una notificación por correo electrónico. Y lo mejor de todo es que es de uso completamente gratuito.
Los análisis de Flurry le brindan información de fallos, modelo de hardware, versión de Android y estadísticas de uso de aplicaciones en vivo. En el nuevo SDK, parecen proporcionar información más detallada sobre el bloqueo http://www.flurry.com/flurry-crash-analytics.html .
Google Firebase es la forma más reciente (2016) de Google de proporcionarle datos de fallos / errores en su teléfono. Inclúyelo en tu archivo build.gradle:
compile ''com.google.firebase:firebase-crash:9.0.0''
Los bloqueos fatales se registran automáticamente sin requerir la intervención del usuario, y también puede registrar bloqueos no fatales u otros eventos como:
try
{
}
catch(Exception ex)
{
FirebaseCrash.report(new Exception(ex.toString()));
}
Para aplicaciones de muestra y propósitos de depuración, uso una solución simple que me permite escribir el seguimiento de pila en la tarjeta SD del dispositivo y / o cargarlo en un servidor. Esta solución ha sido inspirada por Project android-remote-stacktrace (específicamente, las partes de guardar en el dispositivo y cargar en el servidor) y creo que resuelve el problema mencionado por Soonil. No es óptimo, pero funciona y puede mejorarlo si desea usarlo en una aplicación de producción. Si decide cargar los stacktraces en el servidor, puede usar un script php ( index.php
) para verlos. Si está interesado, puede encontrar todas las fuentes a continuación: una clase java para su aplicación y dos scripts php opcionales para el servidor que alberga los stacktraces cargados.
En un contexto (por ejemplo, la actividad principal), llame
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");
?>