【安卓笔记】崩溃日志收集

应用发布之后,总有人反馈说发生crash,但是由于拿不到log,我无法定位问题。后来发现,我们应该收集crash日志,并上传到服务器。

国内有很多的三方机构提供了崩溃收集的sdk,我们可以直接拿来使用,比如,我之前做的app使用的是bugHD(http://bughd.com/)提供的服务。

但是崩溃收集的原理是什么呢?搜索了一下,发现使用的是java中的uncaughtExceptionHandler,我们可以通过Thread.setDefautUncaughtExceptionHandler()设置我们自己的UncaughtExceptionHandler。它其实是一个接口,实现方法即可。


我写的一个demo:

import android.os.Looper;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
/**
 * Created by Rowandjj on 2015/5/19.
 *
 * 崩溃日志收集
 */
public class CrashHandler implements Thread.UncaughtExceptionHandler
{
    private static CrashHandler sInstance = null;
    private static Object lock = new Object();
    private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;
    private CrashHandler()
    {
    }
    public static CrashHandler getInstance()
    {
        if (sInstance == null)
        {
            synchronized (lock)
            {
                if (sInstance == null)
                    sInstance = new CrashHandler();
            }
        }
        return sInstance;
    }
    public void register()
    {
        mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }
    @Override
    public void uncaughtException(Thread thread, Throwable ex)
    {
        //生成日志
        final String filename = cacheLog(ex);
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                Looper.prepare();
                if(filename != null)
                    Toast.makeText(AppEnv.getAppContext(),"程序崩溃了:( \n崩溃日志已保存到"+filename+"",Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }).start();
        try
        {
            Thread.sleep(2000);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        mDefaultExceptionHandler.uncaughtException(thread,ex);
    }
    private String cacheLog(Throwable ex)
    {
        if(ex == null)
            return null;
        Map<String, String> hardwareInfo = HardwareUtils.getHardwareInfo();
        StringBuilder buffer = new StringBuilder();
        for (Map.Entry<String, String> me : hardwareInfo.entrySet())
        {
            buffer.append(me.getKey() + ":" + me.getValue() + "\n");
        }
        buffer.append("packname:" + AppEnv.getPackageName() + "\n");
        buffer.append("versionname:" + AppEnv.getVersionName() + "\n");
        buffer.append("versioncode:" + AppEnv.getVersionCode() + "\n");
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null)
        {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        buffer.append(result);
        long timestamp = System.currentTimeMillis();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.CHINA);
        String time = formatter.format(new Date());
        String filename = "crash-" + time + "-" + timestamp + ".log";
        File file = new File(BasicUtils.getStoreDir(), filename);
        try
        {
            if (!file.exists())
                file.createNewFile();
            FileOutputStream out = new FileOutputStream(file);
            out.write(buffer.toString().getBytes());
            out.close();
            Logger.d(this,file.getAbsolutePath());
            return file.getAbsolutePath();
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        return null;
    }
}

然后在你应用的Application中调用

CrashHandler.getInstance().register();
即可。

应用出现crash时,会把log保存到本地。如果希望上传到服务器,加上一个http上传模块即可。


部分代码没有贴出,大家自己脑补。



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。