如何获取Android崩溃日志?


155

我有一个不在市场上的应用程序(使用调试证书签名),但是每当我的应用程序崩溃时,我都希望获取崩溃日志数据。在哪里可以找到我的应用崩溃的日志?

Answers:


139

如果您的应用正在被其他人下载并在远程设备上崩溃,则您可能需要研究一个Android错误报告库(在本SO文章中引用)。如果只是在您自己的本地设备上,则可以使用LogCat. 即使崩溃发生时该设备未连接到主机,连接该设备并发出adb logcat命令也会下载整个logcat历史记录(至少在一定程度上是缓冲的,通常是大量的日志数据,它不是无限的)。这些选项都可以回答您的问题吗?如果不能,您是否可以尝试澄清您的需求?


2
您能详细说明如何使用adb logcat命令吗?是否在/ SDK / tools目录中运行此文件?我应该注意什么标志吗?等
jesses.co.tt

2
@ jesses.co.tt是的,只需adb logcat从adb所在的任何目录中运行。或者,您可以使用Eclipse插件中包含的SDK工具
Chris Thompson

2
Crashlytics是我使用过的最好的远程异常日志记录软件。它在我所有的应用程序中都消失了,请检查一下。
杰克逊克2014年

adb.exe位于$SDK_DIR/platform-tools/。要显示错误:.\adb.exe logcat -v time *:E
Harun

53

实现此目的的方法是实现Thread.UncaughtExceptionHandler接口,并将其传递到Thread.setDefaultUncaughtExceptionHandler()Activity的开头onCreate()。这是实现类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);
    }
}

注意我们让Android框架的defaultUEH来处理它。

在Activity的顶部注册一个上述类的实例,如下所示:

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

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

该处理程序将跟踪保存在文件中。当ReaderScope下次启动时,它检测到的文件和提示,如果他/她想要通过电子邮件发送给开发者用户。

要通过电子邮件发送堆栈跟踪,请执行以下代码以将其打包到电子邮件中。

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

或者,您也可以使用ACRA错误报告系统。只需将ACRA.jar包含在项目库中,并在启动器活动类声明之前使用以下代码段

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

或者您可以从控制台尝试:

adb logcat -b crash 

这行不会是defaultUEH.uncaughtException(t,e); 无限调用方法uncaughtException()吗?
Mickael BergeronNéron's

@MickaelBergeronNéron否-它只会将相同的Throwable传递给顶级处理程序。
formatBCE


36

您可以从控制台尝试:

adb logcat --buffer=crash 

有关此选项的更多信息:

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

如果使用的是Eclipse,请确保使用调试而不运行。确保您位于调试透视图(右上)中,可能需要多次单击“恢复”(F8)才能打印日志。崩溃日志将在Logcat窗口的底部,双击以全屏显示,并确保滚动到底部。您会看到红色文字表示错误,崩溃跟踪将类似于

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

这个重要的部分是

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)

那些告诉我们,这是onCrate方法中main.java第13行上的数组超出范围异常。


9

您可以使用Apphance。这是一个跨平台的服务(现在主要是Android,iOS和其他正在使用的平台),可以远程调试任何移动设备(现在是Android,iOS-其他正在开发中)。它不仅仅是崩溃日志,实际上还包括更多内容:日志记录,测试人员报告问题,崩溃日志。集成大约需要5分钟。目前,您可以请求访问封闭式Beta。

免责声明:我是Polidea的CTO,该公司是Apphance背后的公司,也是它的共同创始人。

更新:装置不再是内测版!更新2:附件是http://applause.com产品的一部分


2
我只是试了一下,喜欢它。在将Apphance lib集成到您的应用程序时,文档错过了关键点;使用最新版本的Eclipse ADT,您必须将apphance.jar放在 SO答案说明的libs目录中。该github提交显示了我需要对WorldMap应用进行更改以使用Apphance。
JohnnyLambada

@HohnnyLambada感谢您的评论。我们已经更新了文档,以使其更加清晰。
Piotr Duda 2012年

12
这应该没有太多的箭头,它的成本是大多数开发预算(每月2500美元)的10倍以上
user26676 2014年

在此评论发布之日,apphance为404。
DaveP '16

正确。uTest在很早以前就很强壮,然后将他们的整个产品(包括Aphhance的功能)更名为Applause。所以现在是applause.com
Jarek Potiuk '16



4

如果您正在寻找基本的崩溃报告工具,请尝试crashlytics

如果您需要更高级的报告工具,请使用Checkout Gryphonet。它记录所有发生的崩溃,以及导致崩溃的确切代码行,以及自动标记,这些标记向您显示用户在崩溃之前采取的步骤等。

祝好运!



2

我创建了这个库来解决您的所有问题。 Crash Reporter是一个方便的工具,可捕获所有崩溃并将其记录在本地设备中

只需添加此依赖项,就可以了。

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

在本地查找设备中的所有崩溃,并在方便时进行修复。使用易于跟踪的日期和时间格式来保存崩溃。另外,它还提供使用以下方法来捕获记录的异常的API。

CrashRepoter.logException(Exception e)

您用来获取设备崩溃日志的Java类是什么?
Xenolion

Thread.UncaughtExceptionHandler接口用于捕获所有未处理的崩溃。这是相同的github.com/MindorksOpenSource/CrashReporter/blob/master/…的实现。
巴厘岛

好吧,我检查一下...!谢谢
Xenolion

2

这是一个可以帮助您将所有日志转储到文本文件中的解决方案

adb logcat -d > logs.txt


0

如果您只是在手机连接到计算机时查找崩溃日志,请使用Eclipse中的DDMS视图,当您的应用在调试时崩溃时,该报告就位于DDMS中的LogCat中。


0

1)通过USB插入电话(启用了开发人员调试选项)

2)打开“终端”并导航到您的Android SDK(对于Mac):

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

3)从该目录(在您的终端)中的Logcat生成恒定的日志流(对于Mac):

./adb logcat

4)打开崩溃的应用程序以生成崩溃日志

5)Ctrl + C停止终端并查找与崩溃的应用程序关联的日志。它可能会说类似以下内容:

AndroidRuntime: FATAL EXCEPTION: main


0

基于此POST,使用此类替代“ 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) {
}

}

.....

在同一个Java类文件中(Activity).....

Public class MainActivity.....

.....

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

.....


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.