好几年没写博客了,还是大学生的时候记录过很多学习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 [email protected] * @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; } }
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 [email protected] * @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; } } }
<?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包
3、Application或其他地方加入代码
Thread.setDefaultUncaughtExceptionHandler(new GlobalExceptionHandler(getApplicationContext()));
源码下载地址:http://download.csdn.net/detail/zhf198909/7550295
ps:emails.xml里面发送者账号请改成自己的哦