¿Cómo obtener registros de bloqueo de Android?


155

Tengo una aplicación que no está en el mercado (firmada con un certificado de depuración), pero me gustaría obtener datos del registro de fallas cada vez que mi aplicación falla. ¿Dónde puedo encontrar un registro de por qué mi aplicación falló?

Respuestas:


139

Si su aplicación está siendo descargada por otras personas y se bloquea en dispositivos remotos, es posible que desee buscar en una biblioteca de informes de errores de Android (mencionada en esta publicación SO ). Si solo está en su propio dispositivo local, puede usarlo LogCat. incluso si el dispositivo no estaba conectado a una máquina host cuando se produjo el bloqueo, conectar el dispositivo y emitir un adb logcatcomando descargará todo el historial de logcat (al menos en la medida en que está almacenado en un búfer, que generalmente es un montón de datos de registro, simplemente no es infinito). ¿Alguna de esas opciones responde a su pregunta? Si no, ¿puedes intentar aclarar un poco más lo que estás buscando?


2
¿Puedes detallar cómo usar el comando adb logcat? ¿Ejecuto esto dentro del directorio / SDK / tools? ¿Hay alguna bandera que deba tener en cuenta? etc.
jesses.co.tt

2
@ jesses.co.tt Sí, simplemente ejecute adb logcatdesde cualquier directorio en el que se encuentre adb. Alternativamente, puede usar las herramientas SDK incluidas en el complemento Eclipse
Chris Thompson

2
Crashlytics es el mejor software de registro de excepciones remoto que he usado. Sale en todas mis aplicaciones, échale un vistazo.
Jacksonkr

adb.exe se encuentra en $SDK_DIR/platform-tools/. Para mostrar el error:.\adb.exe logcat -v time *:E
Harun

53

La forma de hacerlo es implementar la Thread.UncaughtExceptionHandlerinterfaz y pasarla al Thread.setDefaultUncaughtExceptionHandler()comienzo de su Actividad onCreate(). Aquí está la clase de implementación TopExceptionHandler.

public class TopExceptionHandler implements Thread.UncaughtExceptionHandler {
    private Thread.UncaughtExceptionHandler defaultUEH;
    private Activity app = null;

    public TopExceptionHandler(Activity app) {
        this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
        this.app = app;
    }

    public void uncaughtException(Thread t, Throwable e) {
        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";

        // If the exception was thrown in a background thread inside
        // AsyncTask, then the actual exception can be found with getCause

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

        try {
            FileOutputStream trace = app.openFileOutput("stack.trace", 
                                                        Context.MODE_PRIVATE);
            trace.write(report.getBytes());
            trace.close();
        } catch(IOException ioe) {
        // ...
        }

        defaultUEH.uncaughtException(t, e);
    }
}

Nota Dejamos que el marco predeterminado de AndroidUEH lo maneje.

En la parte superior de su actividad, registre una instancia de la clase anterior como esta:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Thread.setDefaultUncaughtExceptionHandler(new TopExceptionHandler(this));
...

Este controlador guarda la traza en un archivo. Cuando se ReaderScopereinicia la próxima vez, detecta el archivo y le pregunta al usuario si desea enviarlo por correo electrónico al desarrollador.

Para enviar por correo electrónico el seguimiento de pila, ejecute el siguiente código para empaquetarlo en un correo electrónico.

try {
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(ReaderScopeActivity.this.openFileInput("stack.trace")));
    while((line = reader.readLine()) != null) {
        trace += line+"\n";
    }
} catch(FileNotFoundException fnfe) {
    // ...
} catch(IOException ioe) {
    // ...
}

Intent sendIntent = new Intent(Intent.ACTION_SEND);
String subject = "Error report";
String body = "Mail this to appdeveloper@gmail.com: " + "\n" + trace + "\n";

sendIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"readerscope@altcanvas.com"});
sendIntent.putExtra(Intent.EXTRA_TEXT, body);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
sendIntent.setType("message/rfc822");

ReaderScopeActivity.this.startActivity(Intent.createChooser(sendIntent, "Title:"));

ReaderScopeActivity.this.deleteFile("stack.trace");

O también puede usar el Sistema de informe de errores ACRA. Solo incluya el ACRA.jar en las bibliotecas de su proyecto y use el fragmento de código a continuación antes de su declaración de clase de actividad del iniciador

@ReportsCrashes(formKey = "", mailTo = "abc@gmail.com;def@yahoo.com", mode = ReportingInteractionMode.SILENT) 

o puede probar esto desde la consola: -

adb logcat -b crash 

No será la línea defaultUEH.uncaughtException (t, e); llamar al método uncaughtException () infinitamente?
Mickael Bergeron Néron

@ MickaelBergeronNéron no: solo transferirá el mismo Throwable al controlador de nivel superior.
formatBCE


36

Puedes probar esto desde la consola:

adb logcat --buffer=crash 

Más información sobre esta opción:

adb logcat --help

...

  -b <buffer>, --buffer=<buffer>         Request alternate ring buffer, 'main',
                  'system', 'radio', 'events', 'crash', 'default' or 'all'.
                  Multiple -b parameters or comma separated list of buffers are
                  allowed. Buffers interleaved. Default -b main,system,crash.

9

Si está utilizando Eclipse, asegúrese de usar depuración y no ejecutar. Asegúrese de estar en la perspectiva de depuración (arriba a la derecha) Puede que tenga que presionar 'Reanudar' (F8) varias veces para que se imprima el registro. El registro de bloqueo estará en la ventana de Logcat en la parte inferior: haga doble clic para pantalla completa y asegúrese de desplazarse hasta la parte inferior. Verá un texto rojo para errores, el seguimiento del bloqueo será algo así como

09-04 21:35:15.228: ERROR/AndroidRuntime(778): Uncaught handler: thread main exiting due to uncaught exception
09-04 21:35:15.397: ERROR/AndroidRuntime(778): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.dazlious.android.helloworld/com.dazlious.android.helloworld.main}: java.lang.ArrayIndexOutOfBoundsException
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2268) 
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2284)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at android.app.ActivityThread.access$1800(ActivityThread.java:112)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at android.os.Handler.dispatchMessage(Handler.java:99)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at android.os.Looper.loop(Looper.java:123)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at android.app.ActivityThread.main(ActivityThread.java:3948)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at java.lang.reflect.Method.invokeNative(Native Method)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at java.lang.reflect.Method.invoke(Method.java:521)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at dalvik.system.NativeStart.main(Native Method)
09-04 21:35:15.397: ERROR/AndroidRuntime(778): Caused by: java.lang.ArrayIndexOutOfBoundsException
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at com.example.android.helloworld.main.onCreate(main.java:13)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2231)
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     ... 11 more

Las partes importantes para este son

09-04 21:35:15.397: ERROR/AndroidRuntime(778): Caused by: java.lang.ArrayIndexOutOfBoundsException
09-04 21:35:15.397: ERROR/AndroidRuntime(778):     at com.example.android.helloworld.main.onCreate(main.java:13)

esos nos dicen que fue una excepción fuera de límites en la línea 13 de main.java en el método onCrate.


9

Puedes usar Apphance. Este es un servicio multiplataforma (ahora principalmente Android, iOS con otras plataformas en camino) que permite depurar de forma remota cualquier dispositivo móvil (Android, iOS ahora, otros en desarrollo). Es mucho más que un simple registro de fallas, de hecho, es mucho más: registro, reporte de problemas por probadores, registros de fallas. Se tarda unos 5 minutos en integrarse. Actualmente puede solicitar acceso a beta cerrada.

Descargo de responsabilidad: soy CTO de Polidea, una compañía detrás de Apphance y cocreador de la misma.

Actualización: ¡Apphance ya no es beta cerrada! Actualización 2: Apphance está disponible como parte de la oferta http://applause.com


2
Acabo de intentarlo y me gusta. Los documentos perdieron un punto clave al integrar apphance lib en su aplicación; con la última versión de Eclipse ADT, debe colocar apphance.jar en el libsdirectorio tal como explica esta respuesta SO. Esta confirmación de github muestra los cambios que necesitaba hacer en mi aplicación WorldMap para usar apphance.
JohnnyLambada

@HohnnyLambada Gracias por tu comentario. Hemos actualizado la documentación para aclarar esto.
Piotr Duda

12
esto no debería tener tantas flechas hacia arriba que cuesta 10 veces más que la mayoría de los presupuestos de desarrollo ($ 2,500 al mes!)
user26676

la fecha de vencimiento es 404 a la fecha de este comentario.
DaveP

Correcto. UTest ya lo creó hace mucho tiempo, y luego cambió el nombre de toda su oferta (incluida la característica de Aphhance) a Aplausos. Así que ahora es applause.com
Jarek Potiuk


4

Puede usar ACRA de esto . Incluyendo esta biblioteca en sus proyectos y configurándola, puede recibir (en su correo electrónico o gdocs) sus informes de fallas. Perdón por mi mal ingles.


4

Si está buscando una herramienta básica de informe de fallos , pruebe crashlytics .

Si desea una herramienta de informes más avanzada, consulte Gryphonet . Registra todos los bloqueos ocurridos junto con la línea exacta de código que causó el bloqueo junto con marcadores automáticos que le muestran los pasos que el usuario tomó antes del bloqueo y más.

¡Buena suerte!



2

He creado esta biblioteca para resolver todos tus problemas. Crash Reporter es una herramienta útil para capturar todos sus bloqueos e iniciar sesión localmente en el dispositivo

Solo agrega esta dependencia y listo.

compile 'com.balsikandar.android:crashreporter:1.0.1'

Encuentra todos tus bloqueos en el dispositivo localmente y arréglalos a tu conveniencia. Los bloqueos se guardan usando el formato de fecha y hora fácil de rastrear. Además, también proporciona API para capturar excepciones registradas utilizando el siguiente método.

CrashRepoter.logException(Exception e)

¿Cuál es la clase Java que usó para obtener los registros de bloqueo de un dispositivo?
Xenolion

La interfaz Thread.UncaughtExceptionHandler se utiliza para capturar todos los bloqueos no controlados. Aquí está la implementación para el mismo github.com/MindorksOpenSource/CrashReporter/blob/master/… .
Bali

Ok, déjame comprobar esto ...! Gracias
Xenolion

2

Aquí hay una solución que puede ayudarlo a volcar todos los registros en un archivo de texto

adb logcat -d > logs.txt


0

Si solo está buscando el registro de fallas mientras su teléfono está conectado a la computadora, use la vista DDMS en Eclipse y el informe está allí en LogCat dentro de DDMS cuando su aplicación se bloquea durante la depuración.


0

1) Enchufe el teléfono a través de USB (con las opciones de depuración del desarrollador habilitadas)

2) Abra la Terminal y navegue a su Android SDK (para Mac):

cd ~/Library/Android/sdk/platform-tools

3) Logcat desde ese directorio (en su terminal) para generar un flujo constante de registros (para Mac):

./adb logcat

4) Abra su aplicación que se bloquea para generar registros de fallas

5) Ctrl + C para detener el terminal y buscar los registros asociados con la aplicación que se bloquea. Puede decir algo como lo siguiente:

AndroidRuntime: FATAL EXCEPTION: main


0

Base en esta POST , use esta clase como reemplazo de "TopExceptionHandler"

class TopExceptionHandler implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler defaultUEH;
private Activity app = null;
private String line;

public TopExceptionHandler(Activity app) {
    this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
    this.app = app;
}

public void uncaughtException(Thread t, Throwable e) {




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

    // If the exception was thrown in a background thread inside
    // AsyncTask, then the actual exception can be found with getCause

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

    try {
        FileOutputStream trace = app.openFileOutput("stack.trace",
                Context.MODE_PRIVATE);
        trace.write(report.getBytes());
        trace.close();



        Intent i = new Intent(Intent.ACTION_SEND);
        i.setType("message/rfc822");
        i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"kevineyni@gmail.com"});
        i.putExtra(Intent.EXTRA_SUBJECT, "crash report azar");
        String body = "Mail this to kevineyni@gmail.com: " + "\n" + trace + "\n";
        i.putExtra(Intent.EXTRA_TEXT   , body);
        try {
            startActivity(Intent.createChooser(i, "Send mail..."));
        } catch (android.content.ActivityNotFoundException ex) {
           // Toast.makeText(MyActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
        }






      //  ReaderScopeActivity.this.startActivity(Intent.createChooser(sendIntent, "Title:"));

        //ReaderScopeActivity.this.deleteFile("stack.trace");

    } catch(IOException ioe) {
        // ...
    }

    defaultUEH.uncaughtException(t, e);
}

private void startActivity(Intent chooser) {
}

}

.....

en el mismo archivo de clase de Java (Actividad) .....

Public class MainActivity.....

.....

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Thread.setDefaultUncaughtExceptionHandler(new TopExceptionHandler(this));

.....


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.