当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何从Android应用程序获取崩溃数据?》经验,为你挑选了19个好方法。

如何从我的Android应用程序获取崩溃数据(至少是堆栈跟踪)?至少在使用有线电视检索我自己的设备时,最好是从我在野外运行的应用程序的任何实例,以便我可以改进它并使其更加坚固.



1> Kevin Gaudin..:

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

ACRA是一个库,使Android应用程序能够自动将崩溃报告发布到GoogleDoc表单.它面向Android应用程序开发人员,帮助他们在崩溃或行为错误时从应用程序中获取数据.

它很容易在您的应用程序中安装,高度可配置,不需要您在任何地方托管服务器脚本...报告将发送到Google Doc电子表格!


不再支持Google Docs作为后端
这很容易设置和使用.建议用于售前市场使用,甚至可能在之后.
acra的一大优势是可以使用Google API轻松分析和可视化数据,有关如何执行此操作的示例,请参阅http://jberkel.github.com/sms-backup-plus/acra-analysis.
对我来说似乎很不稳定.ACRA本身崩溃并发送了关于自身的崩溃报告而不是相关的应用程序崩溃.-1

2> 小智..:

对于示例应用程序和调试目的,我使用一个简单的解决方案,允许我将堆栈跟踪写入设备的SD卡和/或将其上传到服务器.这个解决方案的灵感来自Project android-remote-stacktrace(特别是保存到设备和上传到服务器的部分),我认为它解决了Soonil提到的问题.它不是最佳的,但它可以工作,如果你想在生产应用程序中使用它,你可以改进它.如果您决定将堆栈跟踪上传到服务器,则可以使用php脚本(index.php)来查看它们.如果你有兴趣,你可以找到下面的所有资源 - 一个用于你的应用程序的java类和两个用于托管上传的栈跟踪的服务器的php scrips.

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

if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
    Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(
            "/sdcard/", "http:///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 nvps = new ArrayList();
        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


index.php

FilenameFiletypeFilesize\n");
    for($index=0; $index < $indexCount; $index++) {
        if ((substr("$dirArray[$index]", 0, 1) != ".") 
                && (strrpos("$dirArray[$index]", ".stacktrace") != false)){ 
            print("");
            print("$dirArray[$index]");
            print("");
            print(filetype($dirArray[$index]));
            print("");
            print(filesize($dirArray[$index]));
            print("\n");
        }
    }
    print("\n");
?>


我认为这会导致某些州/国家的法律问题
注意:`HttpPost httpPost = new HttpPost(url);`如果你的目标是Honeycomb或更高版本,`必须在异步任务(或处理程序......一个单独的线程)中
@Joset,什么样的法律问题,为什么?
@varevarao法律问题(可能),因为您在未经用户同意的情况下使用此代码的"发送至服务器"功能发送敏感设备信息.
defaultExceptionHandler似乎在Activity重新创建后仍然存在。我将答案更新为仅在尚未设置自定义处理程序的情况下才设置默认值。没有它,每个处理程序将保留并调用前一个,直到原始。这会导致重复日志记录问题以及内存泄漏问题。

3> PanosJee..:

您也可以尝试BugSense.BugSense收集并分析了所有崩溃报告,并为您提供有意义的可视化报告.它是免费的,只需1行代码即可集成.

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


我尝试过BugSense,它很棒.简单而新鲜的UI,也非常快.没有愚蠢的功能膨胀.很容易看到最频繁的崩溃,也可以深入了解堆栈跟踪.
BugSense简单易用.但它太昂贵了.我们可以使用Flurry分析和Parse实现相同的错误感知功能.它们都是免费的,易于集成.

4> RoflcoptrExc..:

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

Android Market应用程序的新错误报告功能使开发人员能够从其用户接收崩溃和冻结报告.登录发布商帐户后,报告即可使用.

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



5> sooniln..:

有可能处理这些异常Thread.setDefaultUncaughtExceptionHandler(),但这似乎与Android处理异常的方法混淆.我试图使用这种性质的处理程序:

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

但是,即使重新抛出异常,我也无法获得所需的行为,即在仍然允许Android关闭它发生的组件时记录异常,所以我在一段时间后放弃了它.



6> lingareddyk..:

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

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



7> 小智..:

好吧,我看了rrainn和Soonil提供的样本,我找到了一个解决方案,不会搞错误处理.

我修改了CustomExceptionHandler,因此它存储了我们与新关联的线程中的原始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上的代码进行修改, 您可以在现场登录网络服务器或SD卡,从而获得良好的工作基础.



8> Eefret..:

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

在此输入图像描述


如果您的应用不在Play商店中,您如何让用户发送报告或如何正常工作?您是否可以进行测试?

9> Julie..:

我一直在为我的Android和iOS应用程序使用Crittercism - 在techcrunch上听说过它们.到目前为止,他们非常满意!



10> alocaly..:

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

它基本上是一样的,但我使用的是邮件而不是http连接来发送报告,更重要的是,我在报告中添加了一些信息,如应用程序版本,操作系统版本,手机型号或可用内存. .



11> Vicky Kapadi..:

使用它来捕获异常细节:

String stackTrace = Log.getStackTraceString(exception); 

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



12> Jarek Potiuk..:

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

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

免责声明:我是Polidea的首席技术官,也是该服务的共同创始人.



13> Tushar Pande..:

感谢资源Stackoverflow帮助我找到这个答案.

您可以直接在电子邮件中找到远程Android崩溃报告.请记住,您必须将您的电子邮件放在CustomExceptionHandler类中.

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

所需步骤:

1)在onCreate中你的活动使用你的代码的这一部分.

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

根据我的phpscript,使用这个被覆盖的CustomExceptionHandler类(rrainn).

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 {
        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 nameValuePairs = new ArrayList(
                        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();

    }
}



14> Aleadam..:

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



15> HourGlass..:

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



16> Freek Nortie..:

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

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

在不需要用户输入的情况下自动记录致命崩溃,您还可以记录非致命崩溃或其他类似事件:

try
{

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



17> Vaibhav Jadh..:

如今,Firebase崩溃报告非常流行并且更易于使用。请参考以下链接以获取更多信息: Firebase崩溃报告

希望对您有帮助。



18> Ajit Singh..:

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

安装

android {
    dataBinding {
      enabled = true
    }
}

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

演示版



19> David Rawson..:

尽管此页面上的许多答案很有用,但很容易使它们过时。AppBrain网站汇总了统计信息,可让您找到当前最受欢迎的崩溃报告解决方案:

Android崩溃报告库

您可以看到,在发布此图片时,Crashlytics在5.24%的应用程序和12.38%的安装程序中使用。

推荐阅读
携手相约幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有