如何从我的Android应用程序中获得崩溃数据(至少堆栈跟踪)?至少在我自己的设备上工作时可以通过电缆检索,但理想的情况是,从我的应用程序在野外运行的任何实例中都可以,这样我就可以改进它,使它更可靠。
当前回答
我还找到了一个更好的web应用程序来跟踪错误报告。
https://mint.splunk.com/
配置步骤少。
使用上面的链接登录或注册并配置。一旦你创建了一个应用程序,他们将提供如下所示的一行来配置。
Mint initAndStartSession (YourActivity。这“api_key”);
在应用程序的build.gradl中添加以下内容。
android { ... 存储库{ Maven {url "https://mint.splunk.com/gradle/"} } ... } 依赖关系{ ... 编译”com.splunk.mint:薄荷:4.4.0” ... }
添加上面复制的代码,并将其添加到每个活动中。 Mint.initAndStartSession (YourActivity。这个,”api_key”);
就是这样。你登录并进入应用程序仪表板,你会得到所有的错误报告。
希望它能帮助到别人。
其他回答
For sample applications and debugging purposes, I use a simple solution that allows me to write the stacktrace to the sd card of the device and/or upload it to a server. This solution has been inspired by Project android-remote-stacktrace (specifically, the save-to-device and upload-to-server parts) and I think it solves the problem mentioned by Soonil. It's not optimal, but it works and you can improve it if you want to use it in a production application. If you decide to upload the stacktraces to the server, you can use a php script (index.php) to view them. If you're interested, you can find all the sources below - one java class for your application and two optional php scrips for the server hosting the uploaded stacktraces.
在上下文中(例如主活动),调用
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");
?>
我是Bugsnag的创始人之一,我们正是为此目的而设计的。Bugsnag自动捕获Android应用程序中未处理的异常,并将它们发送到我们的仪表板,在那里您可以优先修复并深入诊断信息。
以下是在选择或构建崩溃报告系统时需要考虑的一些重要事项,以及一些代码片段:
自动检测未处理的异常(示例代码) 收集诊断数据,如内存使用情况、设备信息等(示例代码) 根据根本原因有效地将崩溃组合在一起 允许您跟踪用户在每次崩溃前采取的操作,以帮助重现(示例代码)
如果你想在Android上看到一些关于崩溃处理/报告的最佳实践,你可以查看Bugsnag的崩溃报告库的完整源代码,它是完全开源的,可以自由地把它拆开,并在你自己的应用程序中使用!
你可以直接在Android Studio中做到这一点。只要连接你的手机,运行应用程序,让它崩溃,你就可以直接在Android Studio中查看堆栈跟踪。
迟来的我支持并相信ACRA是最好的选择。它易于设置和配置。我已经创建了一个详细的指南,使用ACRA获取坠机报告,并使用MandrillAp将其发送到我的电子邮件地址。
链接到帖子:https://androidician.wordpress.com/2015/03/29/sending-crash-reports-with-acra-over-email-using-mandrill/
github上的示例项目链接:https://github.com/ayushhgoyal/AcraSample
使用这个来捕获异常细节:
String stackTrace = Log.getStackTraceString(exception);
保存在数据库中,并维护日志。
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件