获取Android应用程序出错信息并将信息发送到指定邮件

前段时间做过一个反馈应用程序Bug的程序,今天和大家分享下

    如果想要获取应用程序的出错信息则比较简单,只需要通过实现 UncaughtExceptionHandler就可以达到目的,那么如何获取Android OS 所有应用程序的出错信息,目前的方式只有通过修改框架层来达到此目的。

(一)首先,我们先来看如何获取应用程序的出错信息:

A) 继承UncaughtExceptionHandler的类

  1. <span style="font-family:SimSun;font-size:18px;">package org.winplus.getex;  
  2.   
  3. import java.lang.Thread.UncaughtExceptionHandler;  
  4.   
  5. import android.content.Context;  
  6. import android.os.Looper;  
  7. import android.util.Log;  
  8. import android.widget.Toast;  
  9.   
  10. public class CrashHandler implements UncaughtExceptionHandler {  
  11.   
  12.     private final static String TAG = "UncaughtExceptionHandler";  
  13.     private Thread.UncaughtExceptionHandler mDefaultHandler;  
  14.     private static CrashHandler mInstance;  
  15.     private Context mContext;  
  16.     private CrashHandler() {  
  17.     }  
  18.   
  19.     /** 获取CrashHandler实例 ,单例模式 */  
  20.     public static CrashHandler getInstance() {  
  21.         if (mInstance == null)  
  22.             mInstance = new CrashHandler();  
  23.         return mInstance;  
  24.     }  
  25.   
  26.     @Override  
  27.     public void uncaughtException(Thread thread, Throwable throwable) {  
  28.         if (!handleException(throwable) && mDefaultHandler != null) {    
  29.             // 如果用户没有处理则让系统默认的异常处理器来处理    
  30.             mDefaultHandler.uncaughtException(thread, throwable);    
  31.         } else {    
  32.             // Sleep一会后结束程序    
  33.             // 来让线程停止一会是为了显示Toast信息给用户,然后Kill程序    
  34.             try {    
  35.                 Thread.sleep(3000);    
  36.             } catch (InterruptedException e) {    
  37.                 Log.e(TAG, "Error : ", e);    
  38.             }    
  39.             android.os.Process.killProcess(android.os.Process.myPid());    
  40.             System.exit(10);    
  41.         }    
  42.     }  
  43.       
  44.     private boolean handleException(Throwable ex) {    
  45.         if (ex == null) {    
  46.             return true;    
  47.         }    
  48.         final String msg = ex.getLocalizedMessage();    
  49.         // 使用Toast来显示异常信息    
  50.         new Thread() {    
  51.             @Override    
  52.             public void run() {    
  53.                 // Toast 显示需要出现在一个线程的消息队列中    
  54.                 Looper.prepare();    
  55.                 Toast.makeText(mContext, "Exception:" + msg, Toast.LENGTH_LONG).show();    
  56.                 Looper.loop();    
  57.             }    
  58.         }.start();    
  59.         return true;    
  60.     }    
  61.       
  62.     public void init(Context context) {    
  63.         mContext = context;    
  64.         mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();    
  65.         Thread.setDefaultUncaughtExceptionHandler(this);    
  66.     }    
  67.       
  68.   
  69. }  
  70. </span>  
B) 初始化并启动获取异常的线程类:CrashApplication

  1. <span style="font-family:SimSun;font-size:18px;">import android.app.Application;  
  2.   
  3. public class CrashApplication extends Application {  
  4.   
  5.     @Override  
  6.     public void onCreate() {  
  7.         super.onCreate();  
  8.   
  9.         CrashHandler crashHandler = CrashHandler.getInstance();  
  10.         // 注册crashHandler  
  11.         crashHandler.init(getApplicationContext());  
  12.     }  
  13. }  
  14. </span>  

C) 记得修改AndroidManifest.xml文件~~~

D) 写一个用于测试的Activity

  1. <span style="font-family:SimSun;font-size:18px;">public class GetExceptionActivity extends Activity {  
  2.     @Override  
  3.     public void onCreate(Bundle savedInstanceState) {  
  4.         super.onCreate(savedInstanceState);  
  5.         setContentView(R.layout.main);  
  6.           
  7.         int i = 1/0;//除数不能为0 这里会抛出异常  
  8.     }  
  9. }</span>  

(二)获取AndroidOS应用程序所有出错信息的思路

    获取应用程序异常的方法我们介绍过了,网上也有很多例子。下面来进入这边文章的重点,说是重点,其实也不难。我们的目的是通过修改最少的代码来获取系统中所有应用程序出错的信息:修改框架层ActivityManagerService类(如果不是特殊的要求,非常不建议修改框架层,当然我们在这里要修改的东西不会影响到什么)

系统出错时一般会弹出一个Dialog,这个Dialog是由frameworks\base\services\java\com\android\server\am\ActivityManagerService.java弹出的,具体的Dialog是frameworks\base\services\java\com\android\server\am\AppErrorDialog.java,所以在这里我们只需要将这个AppErrorDialog改掉,或者在AppErrorDialog中添加一个按钮用于来反馈出错信息的功能,简单的说就是在AppErrorDialog中添加一个按钮,这个按钮通过Intent打开相应的应用程序,并将错误信息发送到应用程序的Activity。

    这里主要给出一个思路吧。

(三)发送邮件

    最后,如何发送邮件呢?Android有几种发送邮件的方式,一种是直接调用系统的邮件,第二种是通过Java Mail的方式发送邮件,第一种并不是我们所需要的,要通过javaMail发送邮件,但Android如何通过JavaMail的方式发送邮件呢?很好,以及有哥们帮我们做了,请看这个:http://code.google.com/p/javamail-android/,只需要下载下面3个Jar包即可:additionnal.jar mail.jar activation.jar

我们来看如何使用这些jar包发邮件

  1. <span style="font-family:SimSun;font-size:18px;">public class MailTool {  
  2.   
  3.     public static void sendMail(String subject, String content) throws MessagingException {  
  4.         Properties props = new Properties();  
  5.         props.put("mail.smtp.host""mail.sina.cn");// 存储发送邮件服务器的信息  
  6.         props.put("mail.smtp.auth""true");// 同时通过验证  
  7.           
  8.         // 基本的邮件会话  
  9.         Session session = Session.getInstance(props);  
  10.         session.setDebug(true);// 设置调试标志  
  11.         // 构造信息体  
  12.         MimeMessage message = new MimeMessage(session);  
  13.   
  14.         // 发件地址  
  15.         Address fromAddress = null;  
  16.         fromAddress = new InternetAddress("abc@sina.cn");  
  17.   
  18.         message.setFrom(fromAddress);  
  19.   
  20.         // 收件地址  
  21.         Address toAddress = new InternetAddress("def@sina.cn");  
  22.         message.addRecipient(Message.RecipientType.TO, toAddress);  
  23.   
  24.         // 解析邮件内容  
  25.         message.setSubject(subject);// 设置信件的标题  
  26.         message.setText(content);// 设置信件内容  
  27.         message.saveChanges(); // implicit with send()//存储信息  
  28.   
  29.         // send e-mail message  
  30.         Transport transport = null;  
  31.         transport = session.getTransport("smtp");  
  32.         transport.connect("mail.sina.cn""abc@sina.cn""winplus.org");  
  33.   
  34.         transport.sendMessage(message, message.getAllRecipients());  
  35.         transport.close();  
  36.     }  
  37.   
  38. }</span>  

发送邮件时一定要注意属性值得设置,不同的邮件服务器有不同的设置,要想实现发送gmail,yahoo等邮箱的发送接收,需要正确的设置,当时就纠结了很久!至于怎么设置,可以先在foxmail中进行设置,看属性就好了。

比如说需要发送接收gmail的邮件,要进行一下设置

  1. <span style="font-family:SimSun;font-size:18px;">    Properties props = new Properties();   
  2.     props.setProperty("mail.transport.protocol""smtp");   
  3.     props.setProperty("mail.host""smtp.gmail.com");   
  4.     props.put("mail.smtp.auth""true");   
  5.     props.put("mail.smtp.port""465");   
  6.     props.put("mail.smtp.socketFactory.port""465");   
  7.     props.put("mail.smtp.socketFactory.class""javax.net.ssl.SSLSocketFactory");   
  8.     props.put("mail.smtp.socketFactory.fallback""false");   
  9.     props.setProperty("mail.smtp.quitwait""false"); </span>  

Ok,这篇文章就到这里吧,主要是和大家分享思路~各位有更好的方法要分享哦

原创文章,欢迎转载,转载请注明出处http://blog.csdn.net/tangcheng_ok

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值