如何从我的Android应用程序获取崩溃数据?

如何从我的Android应用程序获取崩溃数据(至less是堆栈跟踪)? 至less在用自己的设备进行工作的时候,最好是从我的应用程序的任何实例上运行,这样我就可以改进它,使它更加稳定。

您可以尝试ACRA(Android应用程序崩溃报告)库:

ACRA是一个使Android应用程序能够自动将其崩溃报告发布到GoogleDoc表单的库。 它是针对android应用程序开发人员,以帮助他们从应用程序中获取数据,当他们的崩溃或行为错误。

它很容易安装在您的应用程序,高度可configuration,并不需要您在任何地方托pipe服务器脚本…报告发送到一个谷歌Doc电子表格!

对于示例应用程序和debugging目的,我使用一个简单的解决scheme,使我可以将堆栈跟踪写入设备的SD卡并/或上传到服务器。 此解决scheme受到https://code.google.com/archive/p/android-remote-stacktrace/ (具体来说,保存到设备和上传到服务器部分)的启发,我认为它解决了问题Soonil提到。 这不是最优的,但它可以工作,如果你想在生产应用中使用它,你可以改进它。 如果您决定将堆栈跟踪上传到服务器,您可以使用php脚本(index.php)来查看它们。 如果你感兴趣,你可以在下面find所有的源代码 – 为你的应用程序提供一个java类,为托pipe上传的stacktraces的服务器提供两个可选的php脚本。

在上下文中(例如主Activity),调用

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

您也可以尝试BugSense 。 BugSense收集和分析所有崩溃报告,并为您提供有意义的可视化报告。 它是免费的,只有一行代码才能集成。

免责声明:我是联合创始人

在Android 2.2中,现在可以自动从Android电子市场应用程序获取崩溃报告:

Android电子市场应用程序的新bug报告function使开发人员能够收到来自用户的崩溃和冻结报告。 这些报告将在login到其发布者帐户时可用。

http://developer.android.com/sdk/android-2.2-highlights.html

使用Thread.setDefaultUncaughtExceptionHandler()可以处理这些exception,但是这似乎与Android处理exception的方法混淆了。 我试图使用这种性质的处理程序:

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

然而,即使重新抛出exception,我也无法获得所需的行为,即在允许Androidclosures它发生的组件的情况下loggingexception,所以在一段时间后放弃了这个exception。

好吧,我查看了rrainn和Soonil提供的样本,发现了一个不会搞错处理的解决scheme。

我修改了CustomExceptionHandler,所以它存储了与我们关联的Thread的原始UncaughtExceptionHandler。 在新的“uncaughtException”的结尾 – 方法我只是使用存储的UncaughtExceptionHandler调用旧的函数。

在DefaultExceptionHandler类中你需要某事。 喜欢这个:

 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上的代码进行修改,您有一个很好的工作基础,可以将该字段login到您的networking服务器或sd卡。;

我一直在为我的Android和iOS应用使用Crittercism – 在techcrunch上听说过他们。 很高兴与他们到目前为止!

我看到这个问题太老了,希望我的回答对于有同样问题的其他人有帮助。

给Crashlytics一个尝试。 它将深入了解所有设备上的所有崩溃应用程序,并通过电子邮件发送通知给你..最好的部分是它的完全免费使用..

Google Play开发者控制台实际上为您提供了已经崩溃并已发送报告的应用程序的堆栈跟踪,还有一个非常好的图表来帮助您查看信息,请参阅下面的示例:

在这里输入图像描述

我在这里做了我自己的版本: http : //androidblogger.blogspot.com/2009/12/how-to-improve-your-application-crash.html

这基本上是一样的东西,但我用一个邮件,而不是一个HTTP连接发送报告,更重要的是,我添加了一些信息,如应用程序版本,操作系统版本,手机型号或可用内存给我的报告.. 。

用这个来捕获exception的细节:

 String stackTrace = Log.getStackTraceString(exception); 

将其存储在数据库中并维护日志。

您也可以使用整个(简单)服务,而不仅仅是库。 我们公司刚刚为此发布了一项服务: http : //apphance.com 。

它具有一个简单的.jar库(对于Android),您可以在5分钟内添加和集成库,然后库不仅收集崩溃信息,还收集正在运行的应用程序的日志,还可以让testing人员直接从设备报告问题 – 包括整个上下文(设备旋转,无论是否连接到一个WiFi等)。 您可以使用非常好用的Web面板查看日志,在这里您可以跟踪应用程序,崩溃,日志,统计信息等等。 该服务现在处于封闭testing阶段,但您可以请求访问,我们会很快给您。

免责声明:我是Polidea的首席技术官,也是服务的共同创造者。

这是非常暴躁的,但可以在任何地方运行logcat,所以快速和肮脏的黑客是添加到任何catch块getRuntime().exec("logcat >> /sdcard/logcat.log");

谢谢在Stackoverflow中的资源,帮助我find这个答案。

您可以直接在您的电子邮件中find远程Android崩溃报告 。 注意你必须把你的电子邮件放入CustomExceptionHandler类中

 public static String sendErrorLogsTo = "tushar.pandey@virtualxcellence.com" ; 

所需步骤:

1)在您的活动的onCreate使用您的代码的这一部分。

  if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) { Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(this)); } 

第二)根据我的phpscript使用(rrainn)的CustomExceptionHandler类的这个重写版本。

 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 = "tushar.pandey@virtualxcellence.com" ; 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(); } } 

有一个名为fabric的工具,这是一个崩溃分析工具,它可以让你得到崩溃报告,当应用程序部署在现场和开发过程中。 将此工具添加到您的应用程序也很简单。当您的应用程序崩溃时,可以从您的fabric.io仪表板查看该崩溃的报告。 此报告被自动捕获,不会要求用户许可。 无论他/她想发送错误/崩溃报告。 这是完全免费的… https://get.fabric.io/

Google Firebase是Google最新的(2016年)为您提供手机上的崩溃/错误数据的方式。 将其包含在build.gradle文件中:

 compile 'com.google.firebase:firebase-crash:9.0.0' 

致命的崩溃会自动logging而不需要用户input,您也可以logging非致命的崩溃或其他事件,如:

 try { } catch(Exception ex) { FirebaseCrash.report(new Exception(ex.toString())); } 

我们在公司内部使用我们的本土系统,它为我们提供了很好的服务。 这是一个android库,发送崩溃报告到服务器和服务器,接收报告并进行一些分析。 服务器按exception名称,堆栈跟踪,消息分组exception。 它有助于确定需要解决的最重要的问题。 现在我们的服务正在公开testing,所以每个人都可以尝试。 你可以在http://watchcat.co创build账户,或者你可以看看它如何使用演示访问http://watchcat.co/reports/index.php?demo

我发现了一个更好的Web应用程序来跟踪错误报告。

https://mint.splunk.com/

less量的configuration步骤。

  1. 使用上面的链接login或注册并configuration。 一旦你创build了一个应用程序,他们将提供一个如下所示的configuration。
 Mint.initAndStartSession(YourActivity.this, "api_key"); 
  1. 在应用程序的build.gradl中添加以下内容。
 android { ... repositories { maven { url "https://mint.splunk.com/gradle/"} } ... } dependencies { ... compile "com.splunk.mint:mint:4.4.0" ... } 
  1. 添加我们上面复制的代码,并将其添加到每个活动。

    Mint.initAndStartSession(YourActivity.this,“api_key”);

而已。 你login并进入你的应用程序仪表板,你会得到所有的错误报告。

希望它可以帮助别人。

如果你想立即得到答案,你可以使用logcat

$adb shell logcat -f /sdcard/logoutput.txt *:E

如果您的日志中有太多垃圾,请尝试先清除它。

$adb shell logcat -c

然后尝试运行您的应用程序,然后再logcat。

对于备用的崩溃报告/exception跟踪服务,请查看Raygun.io – 它具有一系列用于处理Android崩溃的良好逻辑,包括将其插入到应用程序时体面的用户体验(主要Activity中的两行代码以及一些粘贴到AndroidManifest中的XML行)。

当你的应用程序崩溃,它会自动获取堆栈跟踪,硬/软件的环境数据,用户跟踪信息,你指定的任何自定义数据等。它asynchronous地张贴到API,所以没有阻塞的UI线程,并caching如果没有可用的networking,则将其存储到磁盘

免责声明:我build立了Android提供商:)

尽pipe本页面上的许多答案都很有用,但它们很容易过时。 AppBrain网站汇总的统计数据可以让你find当前最stream行的崩溃报告解决scheme:

http://www.appbrain.com/stats/libraries/tag/crash-reporting/android-crash-reporting-libraries

应用大脑网站

你可以看到在发布这张照片的时候,Crashlytics在5.24%的应用和12.38%的安装中被使用。

刚开始使用ACRA https://github.com/ACRA/acra时,使用Google表单作为后端,设置和使用起来非常简单,这是默认设置。;

但发送报告到Google表单将被弃用(然后删除): https //plus.google.com/118444843928759726538/posts/GTTgsrEQdN6 https://github.com/ACRA/acra/wiki/Notice-on-Google -形成电子表格使用率

无论如何,可以定义您自己的发件人https://github.com/ACRA/acra/wiki/AdvancedUsage#wiki-Implementing_your_own_sender您可以尝试以电子邮件发件人为例。;

用最less的努力就可以发送报告给bugsense: http : //www.bugsense.com/docs/android#acra

NB Bugsense免费账户被限制在500个报告/月

在晚会之后,我支持并相信ACRA是最好的select。 它易于设置和configuration。 我已经创build了一个详细的指导,来自各地的input,使用ACRA获取崩溃报告,并使用MandrillAp将其邮寄到我的电子邮件地址。

链接到post: https : //androidician.wordpress.com/2015/03/29/sending-crash-reports-with-acra-over-email-using-mandrill/

链接到github上的示例项目: https : //github.com/ayushhgoyal/AcraSample

我是我们为此devise的Bugsnag的创始人之一。 Bugsnag会自动捕捉Android应用程序中未处理的exception,并将它们发送到我们的仪表板,您可以在其中优先考虑修补程序并潜入诊断信息。

以下是select或构build崩溃报告系统时要考虑的一些重要事项,以及一些代码片段:

  • 自动检测未处理的exception( 示例代码 )
  • 收集诊断数据,如内存使用情况,设备信息等( 示例代码 )
  • 根本原因有效地将碰撞组合在一起
  • 允许您跟踪用户在每次崩溃前采取的操作以帮助重现( 示例代码 )

如果你想看看关于Android的崩溃处理/报告的一些最佳实践,你可以查看Bugsnag 崩溃报告库的完整源代码,它是完全开源的,你可以把它分开,并在你自己的应用程序中使用!

有这个叫做Sherlock的 android库。 它提供了完整的崩溃报告以及设备和应用信息。 每当发生崩溃时,它会在通知栏中显示通知,并在通知单击时打开崩溃详细信息。 您也可以通过电子邮件或其他共享选项与他人共享崩溃细节。

安装

 android { dataBinding { enabled = true } } compile('com.github.ajitsing:sherlock:1.0.0@aar') { transitive = true } 

演示

在这里输入图像描述

如果您的应用程序正在被其他人下载并在远程设备上崩溃,则可能需要查看Android错误报告库(在此SOpost中引用)。 如果只是在您自己的本地设备上,则可以使用LogCat。 即使设备在发生崩溃时未连接到主机,连接设备并发出adb logcat命令也会下载整个logcat历史logging(至less达到缓冲的程度,通常是logging数据,这只是没有限制)。 这些选项中的任何一个都能回答你的问题 如果不是,你可以尝试澄清你在找什么?

Flurry分析为您提供崩溃信息,硬件模型,Android版本和实时应用使用统计信息。 在新的SDK中,他们似乎提供了更详细的崩溃信息http://www.flurry.com/flurry-crash-analytics.html

现在,一天的Firebase崩溃报告非常受欢迎,也更易于使用。 请参阅以下链接了解更多信息: https : //firebase.google.com/docs/crash/

希望它会帮助你。

谷歌改变了你实际得到的多less崩溃报告。 以前,您只有手动报告错误报告。

自从上一次开发者大会和Android Vitals的介绍以来,您还可以从已启用共享诊断数据的用户那里获得崩溃报告。

您将看到所有从用户select自动共享使用情况和诊断数据的Android设备收集到的崩溃。 数据可用于前两个月。

https://support.google.com/googleplay/android-developer/answer/6083203