如何从我的Android应用程序中获得崩溃数据(至少堆栈跟踪)?至少在我自己的设备上工作时可以通过电缆检索,但理想的情况是,从我的应用程序在野外运行的任何实例中都可以,这样我就可以改进它,使它更可靠。


当前回答

We use our home-grown system inside the company and it serves us very well. It's an android library that send crash reports to server and server that receives reports and makes some analytics. Server groups exceptions by exception name, stacktrace, message. It helps to identify most critical issues that need to be fixed. Our service is in public beta now so everyone can try it. You can create account at http://watchcat.co or you can just take a look how it works using demo access http://watchcat.co/reports/index.php?demo.

其他回答

您也可以尝试[BugSense]原因:垃圾邮件重定向到另一个url。BugSense收集并分析所有崩溃报告,并为您提供有意义的可视化报告。它是免费的,而且只需要一行代码就可以进行集成。

声明:我是联合创始人

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

Android的新错误报告功能 市场应用让开发者能够做到这一点 接收崩溃和冻结报告 他们的用户。报告将会 当他们登录到他们的 出版商账户。

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

感谢资源在Stackoverflow中帮助我找到这个答案。

你可以直接在电子邮件中找到远程Android崩溃报告。记住你必须把你的电子邮件放在CustomExceptionHandler类中。

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

步骤:

1)在onCreate你的活动使用这段代码。

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

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

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

    }
}

我一直在Android和iOS应用中使用cratercism——我在techcrunch上听说过它们。到目前为止,他们都很满意!

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

ACRA是一个库,使Android应用程序自动张贴他们的崩溃报告到GoogleDoc的形式。它是针对android应用程序开发人员,帮助他们从他们的应用程序崩溃或行为错误时获取数据。

它很容易安装在你的应用程序中,高度可配置,不需要你在任何地方托管服务器脚本…报告被发送到谷歌文档电子表格!