下载地址http://download.csdn.net/detail/b275518834/8666865
这个功能很早就有人实现了,我自己尝试调通在加到自己的项目里。
记得要给QQ设置stmp才可以接收到
http://jingyan.baidu.com/article/0f5fb099dffe7c6d8334ea31.html
原理是1:捕捉到android崩溃的事件,
2:开启额外线程将错误日志写入文件
3:发送日志到邮箱
我遇到一些特殊情况,比如用其他同事的手机测试报错,但是手机无法连上电脑
等情况。手机在长时间运行意外终止的情况,无法获得崩溃时日志
核心代码
package org.lxz.utils.android.debug; import java.lang.Thread.UncaughtExceptionHandler; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.lxz.utils.android.info.ApplitionInfo; import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.util.Log; /** * 系统崩溃日志 * @author Aiushtha */ @SuppressLint("SimpleDateFormat") public class SystemCrashLog implements UncaughtExceptionHandler,Runnable{ /**单例*/ private static SystemCrashLog INSTANCE ; /**上下文环境*/ private Context mContext; /**错误*/ private Throwable ex; /**初始化*/ public static SystemCrashLog init(Context context) { return INSTANCE=(INSTANCE==null?new SystemCrashLog(context):INSTANCE); } /**构造方法*/ public SystemCrashLog(Context ctx) { mContext = ctx; Thread.setDefaultUncaughtExceptionHandler(this); } /**捕获异常并处理*/ @Override public void uncaughtException(Thread thread, final Throwable ex) { this.ex=ex; LocalLogRunnable localLogRunnable=new LocalLogRunnable(mContext,ex); String subject="应用程序"+" "+"EmailDemo"+" "+"发生了一个崩溃"; StringBuffer sb=new StringBuffer(); sb.append("android-id:"+ApplitionInfo.getAndroidId(mContext)+"\n") .append("android-code:"+ApplitionInfo.getVersionCode(mContext)+"\n") .append("android-version:"+ApplitionInfo.getVersionName(mContext)+"\n"); localLogRunnable.run(); EmailRunnable emailRunnable=new EmailRunnable(mContext,ex); emailRunnable.setSubject(subject); emailRunnable.setBody(sb.toString()); emailRunnable.setAttachment(localLogRunnable.getLog_file_path()); new Thread(emailRunnable).start();; } public String getApplicationName() { PackageManager packageManager = null; ApplicationInfo applicationInfo = null; try { packageManager = mContext.getApplicationContext().getPackageManager(); applicationInfo = packageManager.getApplicationInfo(mContext.getApplicationContext().getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { applicationInfo = null; } String applicationName = (String) packageManager.getApplicationLabel(applicationInfo); return applicationName; } @Override public void run() { // TODO Auto-generated method stub } }
package org.lxz.utils.android.email; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.security.Security; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.Authenticator; import javax.mail.BodyPart; import javax.mail.Message; 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; import android.util.Log; import android.widget.Toast; public class MailSender extends Authenticator { private String user; private String password; private Session session; private String mailhost = "smtp.gmail.com";//默认用gmail发送 private Multipart messageMultipart; private Properties properties; static { Security.addProvider(new JSSEProvider()); } public MailSender(String user, String password) { this.user = user; this.password = password; properties = new Properties(); properties.setProperty("mail.transport.protocol", "smtp"); // SMTP服务器地址,如smtp.sina.com.cn properties.setProperty("mail.host", mailhost); // properties.setProperty("mail.stmp.from", user); // properties.put("mail.stmp.from", user); properties.put("mail.smtp.auth", "true"); properties.put("mail.smtp.port", "465"); properties.put("mail.smtp.socketFactory.port", "465"); properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); properties.put("mail.smtp.socketFactory.fallback", "false"); properties.setProperty("mail.smtp.quitwait", "false"); session = Session.getDefaultInstance(properties, this); messageMultipart=new MimeMultipart(); } protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(user, password); } public synchronized void sendMail(String subject, String body, String sender, String recipients,String attachment) throws Exception { MimeMessage message = new MimeMessage(session); message.setSender(new InternetAddress(sender));//邮件发件人 // message.setSender(new InternetAddress(sender, false)); message.setSubject(subject);//邮件主题 //设置邮件内容 BodyPart bodyPart=new MimeBodyPart(); bodyPart.setText(body); messageMultipart.addBodyPart(bodyPart); // message.setDataHandler(handler); //设置邮件附件 if(attachment!=null){ bodyPart=new MimeBodyPart(); DataSource dataSource=new FileDataSource(attachment); DataHandler dataHandler=new DataHandler(dataSource); bodyPart.setDataHandler(dataHandler); bodyPart.setFileName(attachment.substring(attachment.lastIndexOf("/")+1)); messageMultipart.addBodyPart(bodyPart); } message.setContent(messageMultipart); if (recipients.indexOf(',') > 0) //多个联系人 message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients)); else //单个联系人 message.setRecipient(Message.RecipientType.TO, new InternetAddress( recipients)); Transport.send(message); } //继承DataSource设置字符编码 public class ByteArrayDataSource implements DataSource { private byte[] data; private String type; public ByteArrayDataSource(byte[] data, String type) { super(); this.data = data; this.type = type; } public ByteArrayDataSource(byte[] data) { super(); this.data = data; } public void setType(String type) { this.type = type; } public String getContentType() { if (type == null) return "application/octet-stream"; else return type; } public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(data); } public String getName() { return "ByteArrayDataSource"; } public OutputStream getOutputStream() throws IOException { throw new IOException("Not Supported"); } public PrintWriter getLogWriter() throws SQLException { // TODO Auto-generated method stub return null; } public int getLoginTimeout() throws SQLException { // TODO Auto-generated method stub return 0; } public void setLogWriter(PrintWriter out) throws SQLException { // TODO Auto-generated method stub } public void setLoginTimeout(int seconds) throws SQLException { // TODO Auto-generated method stub } public boolean isWrapperFor(Class<?> arg0) throws SQLException { // TODO Auto-generated method stub return false; } public <T> T unwrap(Class<T> arg0) throws SQLException { // TODO Auto-generated method stub return null; } public Connection getConnection() throws SQLException { // TODO Auto-generated method stub return null; } public Connection getConnection(String theUsername, String thePassword) throws SQLException { // TODO Auto-generated method stub return null; } } public String getMailhost() { return mailhost; } public void setMailhost(String mailhost) { this.mailhost = mailhost; properties.setProperty("mail.host", this.mailhost); } }