Android崩溃日志收集

好几年没写博客了,还是大学生的时候记录过很多学习Android时候遇到的问题以及解决方案。转眼3,4年过去了,前段时间看了看自己以前写的博客,发现水准比较低,所以把以前的博客都给删了,这也间接说明自己成长了许多。本人文采不咋样,所以废话不多说,今天给大家带来一个小工具,一般我们做的App上线后都会去收集客户端崩溃的日志,有很多第三方帮我们做了这个工具,从各种维度进行了分析,但这种一般作为开发者不会去看的,运营专员才会去看。开发讲究的就是立马通知我哪里哪里出问题了,马上修改,好了,那我们就借助java发送邮件的功能在Android中集成一个崩溃信息邮件通知功能吧。


一、准备java发送邮件所需要的jar包


二、建立Android项目

这里只简单介绍几个重要的类

1、自己的Application代码片段

@Override
    public void onCreate()
    {
        super.onCreate();
        Thread.setDefaultUncaughtExceptionHandler(new GlobalExceptionHandler(getApplicationContext()));
    }
2、全局异常类

package com.android.exception2email;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.xml.sax.Attributes;

import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.sax.Element;
import android.sax.ElementListener;
import android.sax.EndTextElementListener;
import android.sax.RootElement;
import android.util.Xml;


/**
 * 全局异常处理
 * @author hiphonezhu@gmail.com
 * @version [2014-6-25]
 */
public final class GlobalExceptionHandler implements
    Thread.UncaughtExceptionHandler
{
    private static final String SMTP_SINA_COM = "smtp.sina.com";
    private static final String LINE_SEPARATOR = System
        .getProperty("line.separator");
    private Thread.UncaughtExceptionHandler defaultHandler;
    private boolean caughtException = false;
    private String clientInfo;

    private Context appContext;
    /**
     * 全局错误处理构造函数
     */
    public GlobalExceptionHandler(Context appContext)
    {
        this.appContext = appContext;
        this.defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        // 收集客户端信息
        this.clientInfo = collectClientInfo();
        loadEmails();
    }
    
    private List<AccountInfo> fromEmailList = new ArrayList<AccountInfo>();
    private List<String> toEmailList = new ArrayList<String>();
    private AccountInfo mailInfo = null;
    /**
     * 读取邮件列表信息
     */
    private void loadEmails()
    {
        try
        {
            InputStream is = appContext.getAssets().open("emails.xml");
            RootElement document = new RootElement("addrs");
            Element fromList = document.getChild("from-list");
            Element itemFrom = fromList.getChild("item");
            itemFrom.setElementListener(new ElementListener()
            {
                
                @Override
                public void end()
                {
                    fromEmailList.add(mailInfo);
                }
                
                @Override
                public void start(Attributes attributes)
                {
                    mailInfo = new AccountInfo();
                }
            });
            itemFrom.getChild("account").setEndTextElementListener(new EndTextElementListener()
            {
                @Override
                public void end(String body)
                {
                    mailInfo.setAccount(body);
                }
            });
            itemFrom.getChild("password").setEndTextElementListener(new EndTextElementListener()
            {
                @Override
                public void end(String body)
                {
                    mailInfo.setPassword(body);
                }
            });
            Element toList = document.getChild("to-list");
            Element itemTo = toList.getChild("item");
            itemTo.setEndTextElementListener(new EndTextElementListener()
            {
                @Override
                public void end(String body)
                {
                    toEmailList.add(body);
                }
            });
            Xml.parse(new InputStreamReader(is), document.getContentHandler());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    
    /**
     * 返回版本号
     * @return
     */
    public String getVerName()
    {
        String verName = "";
        try
        {
            verName = appContext.getPackageManager().getPackageInfo(appContext.getPackageName(),
                    0).versionName;
        }
        catch (NameNotFoundException e)
        {
            e.printStackTrace();
        }
        return verName;
    }

    /**
     * 返回包名
     * @return
     */
    public String getPackageName()
    {
        return appContext.getPackageName();
    }
    
    /**
     * 捕获到异常
     * 
     * @param thread 异常线程
     * @param throwable 异常信息
     */
    @Override
    public void uncaughtException(final Thread thread, final Throwable throwable)
    {
        if (caughtException)
        {
            defaultHandler.uncaughtException(thread,
                throwable);
            return;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos);
        throwable.printStackTrace(ps);
        final String errorMsg = new String(baos.toByteArray());
        final String mailContent = errorMsg + LINE_SEPARATOR + LINE_SEPARATOR
            + clientInfo;

        // 将报错信息发送到指定的邮箱
        Thread sendMailThread = new Thread()
        {
            @Override
            public void run()
            {
                try
                {
                    String subject =  getPackageName() + "_v" + getVerName() + " Crash Report";
                    Properties props = new Properties();
                    props.put("mail.smtp.host",
                        SMTP_SINA_COM);
                    props.put("mail.smtp.auth",
                        "true");
                    MailUtil.MailInfo mailInfo = new MailUtil.MailInfo();
                    int index = (int) (Math.floor(Math
                            .random() * fromEmailList.size()));
                    AccountInfo info = fromEmailList.get(index);
                    mailInfo.setFrom(info.getAccount());
                    mailInfo.setPassword(info.getPassword());
                    mailInfo.setSmtpHost(SMTP_SINA_COM);
                    mailInfo.setNeedAuth(true);
                    String[] tos = new String[toEmailList.size()];
                    toEmailList.toArray(tos);
                    mailInfo.setToList(tos);
                    mailInfo.setSubject(subject);
                    mailInfo.setContent(mailContent);
                    try
                    {
                        MailUtil.sendMail(mailInfo);
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
                finally 
                {
                    if (!handleException() && defaultHandler != null)
                    {
                        defaultHandler.uncaughtException(thread, throwable);
                    }
                }
            }
        };
        sendMailThread.start();
    }
    
    /** 
     * 自定义错误处理、收集错误信息 、发送错误报告等操作均在此完成. 
     * @return true:如果处理了该异常信息;否则返回false. 
     */  
    private boolean handleException() 
    {  
        try 
        {
            android.os.Process.killProcess(android.os.Process.myPid());  
            System.exit(1);
            return true;
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
            return false;
        }
    }  

    private String collectClientInfo()
    {
        StringBuilder systemInfo = new StringBuilder();
        systemInfo.append("CLIENT-INFO");
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Id: ");
        systemInfo.append(Build.ID);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Display: ");
        systemInfo.append(Build.DISPLAY);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Product: ");
        systemInfo.append(Build.PRODUCT);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Device: ");
        systemInfo.append(Build.DEVICE);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Board: ");
        systemInfo.append(Build.BOARD);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("CpuAbility: ");
        systemInfo.append(Build.CPU_ABI);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Manufacturer: ");
        systemInfo.append(Build.MANUFACTURER);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Brand: ");
        systemInfo.append(Build.BRAND);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Model: ");
        systemInfo.append(Build.MODEL);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Type: ");
        systemInfo.append(Build.TYPE);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Tags: ");
        systemInfo.append(Build.TAGS);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("FingerPrint: ");
        systemInfo.append(Build.FINGERPRINT);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Version.Incremental: ");
        systemInfo.append(Build.VERSION.INCREMENTAL);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Version.Release: ");
        systemInfo.append(Build.VERSION.RELEASE);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("SDK: ");
        systemInfo.append(Build.VERSION.SDK);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("SDKInt: ");
        systemInfo.append(Build.VERSION.SDK_INT);
        systemInfo.append(LINE_SEPARATOR);
        systemInfo.append("Version.CodeName: ");
        systemInfo.append(Build.VERSION.CODENAME);
        systemInfo.append(LINE_SEPARATOR);
        String clientInfomation = systemInfo.toString();
        systemInfo.delete(0, systemInfo.length());
        return clientInfomation;
    }
}

3、邮件发送辅助类

package com.android.exception2email;
import java.util.Date;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
/**
 * 邮件操作封装
 * @author hiphonezhu@gmail.com
 * @version [2014-6-25]
 */
public abstract class MailUtil
{

    /**
     * 发送邮件
     * 
     * @param info 邮件信息
     * @throws MessagingException MessagingException
     */
    public static void sendMail(final MailInfo info) throws MessagingException
    {
        Properties props = new Properties();
        props.put("mail.smtp.host",
            info.getSmtpHost());
        props.put("mail.smtp.auth",
            String.valueOf(info.isNeedAuth()));
        Session session = Session.getDefaultInstance(props,
            new Authenticator()
            {
                @Override
                public PasswordAuthentication getPasswordAuthentication()
                {
                    return new PasswordAuthentication(info.getFrom(),
                        info.getPassword());
                }
            });
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(info.getFrom()));
        InternetAddress[] address = new InternetAddress[info.getToList().length];
        for (int i = 0; i < info.getToList().length; i++)
        {
            address[i] = new InternetAddress(info.getToList()[i]);
        }
        msg.setRecipients(Message.RecipientType.TO,
            address);
        Date current = new Date();
        msg.setSubject(info.getSubject());
        Multipart mp = new MimeMultipart();
        MimeBodyPart mbpContent = new MimeBodyPart();
        mbpContent.setText(info.getContent());
        mp.addBodyPart(mbpContent);
        msg.setContent(mp);
        msg.setSentDate(current);
        Transport.send(msg,
            address);

    }

    /**
     * 邮件信息
     */
    public static class MailInfo
    {
        private String from;
        private String password;
        private String[] toList;
        private String subject;
        private String content;
        private boolean needAuth;
        private String smtpHost;

        public String getFrom()
        {
            return from;
        }

        public void setFrom(String from)
        {
            this.from = from;
        }

        public String getPassword()
        {
            return password;
        }

        public void setPassword(String password)
        {
            this.password = password;
        }

        public String[] getToList()
        {
            return toList;
        }

        public void setToList(String[] toList)
        {
            this.toList = toList;
        }

        public String getSubject()
        {
            return subject;
        }

        public void setSubject(String subject)
        {
            this.subject = subject;
        }

        public String getContent()
        {
            return content;
        }

        public void setContent(String content)
        {
            this.content = content;
        }

        public boolean isNeedAuth()
        {
            return needAuth;
        }

        public void setNeedAuth(boolean needAuth)
        {
            this.needAuth = needAuth;
        }

        public String getSmtpHost()
        {
            return smtpHost;
        }

        public void setSmtpHost(String smtpHost)
        {
            this.smtpHost = smtpHost;
        }
    }
}

4、邮件发送者和接受者列表(防止同一个账号发送多次邮件被服务器拒绝,这里我们尽量申请多个Email账号),xml文件可配置,增加灵活性


<?xml version="1.0" encoding="utf-8"?>
<addrs>
    <from-list>
        <item>
            <account>xxx@xxx</account>
            <password>xxx</password>
        </item>
        <item>
            <account>xxx@xxx</account>
            <password>xxx</password>
        </item>
        <item>
            <account>xxx@xxx</account>
            <password>xxx</password>
        </item>
        <item>
            <account>xxx@xxx</account>
            <password>xxx</password>
        </item>
        <item>
            <account>xxx@xxx</account>
            <password>xxx</password>
        </item>
    </from-list>
	<to-list>
	    <item>xxx@xxx</item>
	</to-list>
</addrs>

我们跑起来看看啊



点击崩溃,我的qq邮箱收到邮件了,信息还是比较全面的




总结:

1、引入这些jar包

2、新建emails.xml文件,内容见上下文

3、Application或其他地方加入代码

Thread.setDefaultUncaughtExceptionHandler(new GlobalExceptionHandler(getApplicationContext()));


源码下载地址:http://download.csdn.net/detail/zhf198909/7550295

ps:emails.xml里面发送者账号请改成自己的哦

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值