Android 如何收集已发布程序的崩溃信息

瘦de刻骨铭心

瘦de刻骨铭心

2016-02-19 09:03

下面是个超简单的Android 如何收集已发布程序的崩溃信息教程,图老师小编精心挑选推荐,大家行行好,多给几个赞吧,小编吐血跪求~

我们写程序的时候都希望能写出一个没有任何Bug的程序,期望在任何情况下都不会发生程序崩溃。不过理想是丰满的,现实是骨感的。没有一个程序员能保证自己写的程序绝对不会出现异常崩溃。特别是针对用户数达到几十万几百万的程序,当你用户数达到一定数量级后,就算你的程序出现个别异常崩溃情况也不用惊讶。

既然我们写的程序都有可能发生异常崩溃,如果是还没发布的程序,我们可以通过测试抓取Log来分析。不过针对已经发布的程序,我们没法重现现象,所以让用户反馈程序异常信息就很重要。下面我们说说如何收集程序运行过程的异常信息。

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)

1、Android异常捕获接口
代码如下:

//当线程因未捕获的异常而突然终止时,调用处理程序的接口
static interface UncaughtExceptionHandler

2、设置线程捕获异常
从上面的接口我们可以看到,这个接口是针对线程来说,也就是说我们如果需要监控某个线程运行情况,只要把这个接口实现了,然后把监控方法设置到具体的线程里面即可。一般来说,我们最需要监控的就是我们的UI线程也就是主线程。
代码如下:

//设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

3、UncaughtExceptionHandler 实例
代码如下:

class MythouCrashHandler implements UncaughtExceptionHandler
{
    private static final String TAG = "MythouCrashHandler----";
    private UncaughtExceptionHandler defaultUEH;
  //构造函数,获取默认的处理方法
    public MythouCrashHandler()
    {
        this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
    }
  //这个接口必须重写,用来处理我们的异常信息
    @Override
    public void uncaughtException(Thread thread, Throwable ex)
    {
        final Writer result = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(result);
     //获取跟踪的栈信息,除了系统栈信息,还把手机型号、系统版本、编译版本的唯一标示
        StackTraceElement[] trace = ex.getStackTrace();
        StackTraceElement[] trace2 = new StackTraceElement[trace.length+3];
        System.arraycopy(trace, 0, trace2, 0, trace.length);
        trace2[trace.length+0] = new StackTraceElement("Android", "MODEL", android.os.Build.MODEL, -1);
        trace2[trace.length+1] = new StackTraceElement("Android", "VERSION", android.os.Build.VERSION.RELEASE, -1);
        trace2[trace.length+2] = new StackTraceElement("Android", "FINGERPRINT", android.os.Build.FINGERPRINT, -1);
    //追加信息,因为后面会回调默认的处理方法
        ex.setStackTrace(trace2);
        ex.printStackTrace(printWriter);
     //把上面获取的堆栈信息转为字符串,打印出来
        String stacktrace = result.toString();
        printWriter.close();
        Log.e(TAG, stacktrace);
        //这里把刚才异常堆栈信息写入SD卡的Log日志里面
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
        {
            String sdcardPath = Environment.getExternalStorageDirectory().getPath();
            writeLog(stacktrace, sdcardPath + "/mythou");
        }
        defaultUEH.uncaughtException(thread, ex);
    }
  //写入Log信息的方法,写入到SD卡里面
    private void writeLog(String log, String name)
    {
        CharSequence timestamp = DateFormat.format("yyyyMMdd_kkmmss", System.currentTimeMillis());
        String filename = name + "_" + timestamp + ".log";
        try
        {
            FileOutputStream stream = new FileOutputStream(filename);
            OutputStreamWriter output = new OutputStreamWriter(stream);
            BufferedWriter bw = new BufferedWriter(output);
       //写入相关Log到文件
            bw.write(log);
            bw.newLine();
            bw.close();
            output.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

上面就是实现了获取处理跟踪信息的方法,上面的方法是参照VLC的异常处理机制编写的。做了一些简单修改。不过上面只是获取了异常信息,如果程序安装到用户机器上,我们没法获取到这些信息,总不能让用户把机器拿过来给你,然后你把Log拷贝出来吧。(这个我以前做嵌入式的时候到试过,让客户把机器拿过来,拷贝里面的Log,那时候做的机器无法联网。现在想起来都纠结,O(∩_∩)O哈哈~) 为了不再纠结,我们需要一个可以把Log发送到我们服务器的功能,下面是把一个服务信息发送到我们指定服务器功能。

3、通过网络发送Log
代码如下:

   public class SendCrashLog extends AsyncTaskString, String, Boolean
    {
        public SendCrashLog() { }
        @Override
        protected Boolean doInBackground(String... params)
        {
            if (params[0].length() == 0)
                return false;
            HttpClient httpClient = new DefaultHttpClient();
       //你的服务器,这里只是举个例子。把异常信息当作http请求发送到服务器
            HttpPost httpPost = new HttpPost("http://www.mythou/getlog.php");
       //这里把相关的异常信息转为http post请求的数据参数
            try {
                ListNameValuePair nameValuePairs = new ArrayListNameValuePair(1);
                nameValuePairs.add(new BasicNameValuePair("model", params[0]));
                nameValuePairs.add(new BasicNameValuePair("device", params[1]));
                httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
         //发送相关请求信息
                httpClient.execute(httpPost);
            } catch (ClientProtocolException e) {
                e.printStackTrace();
                return false;
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
            Log.d(TAG, "Device model sent.");
            return true;
        }
        @Override
        protected void onPostExecute(Boolean result) {
        }
    }

上面就是我上一篇文章讲的异步任务的使用,我们在异步任务里面编写了一个发送http请求的服务,用来把相关的异常信息发送到我们指定的服务器上面。这个需要你的服务器解析发送的http请求,这个难度不大,一般做个web的人都知道如何做。在上面的异常处理里面再调用这里的发送方法:
代码如下:

SendCrashLogsendLog = new SendCrashLog();
//刚才的异常信息字符串
sendLog .execute(stacktrace);

通过上面的方法就可以把异常信息发送到指定的服务器,也就可以跟踪客户使用软件的情况,方便我们修改程序的问题。当然这个信息收集一般都隐私和后台流量问题,这个需要在程序里面做点提示,免得背上流氓软件的骂名。

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)
展开更多 50%)
分享

猜你喜欢

Android 如何收集已发布程序的崩溃信息

编程语言 网络编程
Android 如何收集已发布程序的崩溃信息

用JSP编写通用信息发布程序

Java JAVA基础
用JSP编写通用信息发布程序

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

火柴如何编辑已发布的内容

手机软件 应用软件
火柴如何编辑已发布的内容

58同城怎么发布租房信息 如何认证58同城发布的信息

58同城 软件教程 电脑软件 应用软件
58同城怎么发布租房信息 如何认证58同城发布的信息

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

58同城如何发布招聘信息?

58同城 手机软件 应用软件
58同城如何发布招聘信息?

Android 后台发送邮件示例 (收集应用异常信息+Demo代码)

编程语言 网络编程
Android 后台发送邮件示例 (收集应用异常信息+Demo代码)

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

oracle 彻底删除方法

oracle 彻底删除方法

WPS如何使用卡方检验

WPS如何使用卡方检验
下拉加载更多内容 ↓