Como obter registros de falhas do Android?


155

Eu tenho um aplicativo que não está no mercado (assinado com um certificado de depuração), mas gostaria de obter dados do log de falha sempre que meu aplicativo falhar. Onde posso encontrar um log do motivo pelo qual meu aplicativo travou?

Respostas:


139

Se o aplicativo estiver sendo baixado por outras pessoas e travando em dispositivos remotos, convém consultar uma biblioteca de relatórios de erros do Android (mencionada nesta postagem do SO ). Se for apenas no seu próprio dispositivo local, você poderá usar LogCat. Mesmo que o dispositivo não tenha sido conectado a uma máquina host quando ocorreu a falha, conectar o dispositivo e emitir um adb logcatcomando fará o download de todo o histórico do logcat (pelo menos na medida em que ele é armazenado em buffer, o que geralmente é uma quantidade enorme de dados de log, mas não é infinito). Alguma dessas opções responde à sua pergunta? Caso contrário, você pode tentar esclarecer um pouco mais o que está procurando?


2
você pode detalhar como usar o comando adb logcat? Eu executo isso dentro do diretório / SDK / tools? Há alguma sinalização que devo observar? etc
jesses.co.tt

2
@ jesses.co.tt Yep, basta executar adb logcata partir de qualquer adb diretório está localizado em Alternativamente, você pode usar as ferramentas do SDK incluído no plugin Eclipse.
Chris Thompson

2
O Crashlytics é o melhor software de registro remoto de exceção que eu já usei. Ele sai em todos os meus aplicativos, confira.
Jacksonkr

adb.exe está localizado em $SDK_DIR/platform-tools/. Para mostrar erro:.\adb.exe logcat -v time *:E
Harun

53

A maneira de fazer isso é implementar a Thread.UncaughtExceptionHandlerinterface e passá-la para Thread.setDefaultUncaughtExceptionHandler()o início das suas atividades onCreate(). Aqui está a classe de implementação 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 Nós deixamos o defaultUEH da estrutura do Android lidar com isso.

Na parte superior da sua atividade, registre uma instância da classe acima como esta:

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

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

Este manipulador salva o rastreamento em um arquivo. Quando ReaderScopereiniciar na próxima vez, ele detecta o arquivo e solicita ao usuário se ele deseja enviá-lo por e-mail ao desenvolvedor.

Para enviar por email o rastreamento de pilha, execute o código a seguir para compactá-lo em um email.

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

Ou você também pode usar o Sistema de Relatório de Erros ACRA. Basta incluir o ACRA.jar nas bibliotecas do projeto e usar o trecho de código abaixo antes da declaração da classe de atividade do iniciador

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

ou Você pode tentar isso no console: -

adb logcat -b crash 

A linha não será o padrãoUEH.uncaughtException (t, e); chamar o método uncaughtException () infinitamente?
Mickael Bergeron Néron

@ MickaelBergeronNéron não - apenas transferirá o mesmo Throwable para o manipulador de nível superior.
formatBCE


36

Você pode tentar isso no console:

adb logcat --buffer=crash 

Mais informações sobre esta opção:

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

Se você estiver usando o Eclipse, certifique-se de usar depuração e não executar. Verifique se você está na perspectiva de depuração (canto superior direito). Talvez seja necessário pressionar 'Continuar' (F8) algumas vezes para que o log seja impresso. O log de falha estará na janela Logcat na parte inferior - clique duas vezes para exibir em tela cheia e certifique-se de rolar para a parte inferior. Você verá erros em texto em vermelho. O rastreamento de falhas será algo 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

As partes importantes para este são

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)

aqueles nos dizem que foi uma exceção fora dos limites na linha 13 do main.java no método onCrate.


9

Você pode usar o Apphance. Este é um serviço de plataforma cruzada (agora principalmente Android, iOS e outras plataformas a caminho) que permite depurar remotamente qualquer dispositivo móvel (Android, iOS agora - outros em desenvolvimento). É muito mais do que apenas um crashlog, na verdade é muito mais: registro, relatório de problemas por testadores, logs de travamento. Demora cerca de 5 minutos para integrar. Atualmente, você pode solicitar acesso ao beta fechado.

Isenção de responsabilidade: Eu sou CTO da Polidea, uma empresa por trás da Apphance e co-criadora dela.

Atualização: Apphance não é mais beta fechado! Atualização 2: o Apphance está disponível como parte da oferta http://applause.com


2
Eu apenas tentei Apphance e gosto. Os documentos perderam um ponto chave ao integrar a lib de apphance ao seu app; com a versão mais recente do Eclipse ADT, você deve colocar o apphance.jar no libsdiretório, conforme explica esta resposta do SO. Este commit do github mostra as alterações que eu precisava fazer no meu aplicativo WorldMap para usar o apphance.
JohnnyLambada

@HohnnyLambada Obrigado pelo seu comentário. Atualizamos a documentação para deixar isso mais claro.
Piotr Duda

12
isso não deve obter tantos setas para cima custa 10x mais do que a maioria dos orçamentos de desenvolvimento (US $ 2.500 por mês!)
user26676

apphance é 404 na data deste comentário.
DaveP

Corrigir. Já foi lançado há muito tempo pelo uTest, que renomeou toda a sua oferta (incluindo o recurso de Aphhance) para Aplausos. Então agora é aplausos.com
Jarek Potiuk 19/02/16


4

Você pode usar o ACRA a partir disso . Incluindo essa biblioteca em seus projetos e configurando-a, você pode receber (em seu email ou gdocs) os relatórios de falhas deles. Desculpe pelo meu inglês ruim.


4

Se você estiver procurando por uma ferramenta básica de relatório de falhas, tente o crashlytics .

Se você deseja uma ferramenta de relatório mais avançada, o Checkout Gryphonet . Ele registra todas as falhas ocorridas junto com a linha exata de código que causou a falha, além de marcadores automáticos que mostram as etapas que o usuário executou antes da falha e muito mais.

Boa sorte!



2

Eu criei esta biblioteca para resolver todos os seus problemas. Crash Reporter é uma ferramenta útil para capturar todas as falhas e registrá-las localmente no dispositivo

Basta adicionar essa dependência e você estará pronto.

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

Encontre todas as falhas no dispositivo localmente e corrija-as conforme sua conveniência. As falhas são salvas usando o formato de data e hora fácil de rastrear. Além disso, ele também fornece API para capturar exceções registradas usando o método abaixo.

CrashRepoter.logException(Exception e)

Qual é a classe Java que você usou para obter os Crash Logs de um dispositivo?
Xenolion

A interface Thread.UncaughtExceptionHandler é usada para capturar todas as falhas não tratadas. Aqui está a implementação do mesmo github.com/MindorksOpenSource/CrashReporter/blob/master/… .
Bali

Ok, deixa eu ver isso ...! Obrigado
Xenolion

2

Aqui está uma solução que pode ajudá-lo a despejar todos os logs em um arquivo de texto

adb logcat -d > logs.txt


0

Se você estiver apenas procurando o log de falha enquanto o telefone estiver conectado ao computador, use a visualização DDMS no Eclipse e o relatório estará no LogCat no DDMS quando o aplicativo travar durante a depuração.


0

1) Conecte o telefone via USB (com opções de depuração do desenvolvedor ativadas)

2) Abra o Terminal e acesse o Android SDK (para Mac):

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

3) Logcat desse diretório (no seu terminal) para gerar um fluxo constante de logs (para Mac):

./adb logcat

4) Abra o aplicativo que trava para gerar logs de travamento

5) Ctrl + C para parar o terminal e procurar os logs associados ao aplicativo que trava. Pode dizer algo como o seguinte:

AndroidRuntime: FATAL EXCEPTION: main


0

Com base neste POST , use essa classe como substituição 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) {
}

}

.....

no mesmo arquivo de classe java (Activity) .....

Public class MainActivity.....

.....

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

.....


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.