当前位置:   article > 正文

Android 捕捉app系统中未处理的异常_android拦截未处理异常

android拦截未处理异常

转载请标明出处:http://blog.csdn.net/u011546655/article/details/45566741


一:为什么要处理?


其实我们都知道,在开发过程中,自己的app系统或许有许多隐藏的异常,自己没有捕捉到,那么关于异常的捕捉,这是相当重要的,如果系统发生崩溃,那么至少也可以让系统挂在系统之内,不会发现什么系统直接退了,或者是卡死,这样做,能够使得用户体验效果更加,自己也可以发现用户到底出现什么异常,便于自己以后好处理这个问题,优化处理自己的系统。


二:如何解决

在Android 开发中,自身其实带有一个系统默认的异常处理接口,UncaughtExceptionHandler,该接口呢,能够很好的处理程序中发生的异常,所以,往往开发者都喜欢使用它,而且它也是一个非常简单好用的东西。


三:具体实现


(1)实现UncaughtExceptionHandler接口的类

  1. package com.x1.tools;
  2. import java.lang.Thread.UncaughtExceptionHandler;
  3. import android.app.ActivityManager;
  4. import android.content.ComponentName;
  5. import android.content.Context;
  6. import android.os.Looper;
  7. import android.util.Log;
  8. import com.x1.dao.SubmitConfigBugs;
  9. import com.x1.ui.R;
  10. /**
  11. * 未捕获异常捕捉类
  12. *
  13. * @author zengtao 2015年5月6日
  14. *
  15. *
  16. */
  17. public class CrashHandlers implements UncaughtExceptionHandler {
  18. public static final String TGA = "CrashHandlers";
  19. // 系统默认的UncaughtException处理类
  20. private Thread.UncaughtExceptionHandler mDefaultHandler;
  21. // CrashHandler实例
  22. private static CrashHandlers instance;
  23. // 程序的Context对象
  24. private Context mContext;
  25. private GetPhoneInfo phone;
  26. /** 保证只有一个CrashHandler实例 */
  27. private CrashHandlers() {
  28. }
  29. /** 获取CrashHandler实例 ,单例模式 */
  30. public synchronized static CrashHandlers getInstance() {
  31. if (instance == null) {
  32. instance = new CrashHandlers();
  33. }
  34. return instance;
  35. }
  36. /**
  37. * 初始化
  38. *
  39. * @param context
  40. */
  41. public void init(Context context) {
  42. mContext = context;
  43. // 获取系统默认的UncaughtException处理器
  44. mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
  45. // 设置该CrashHandler为程序的默认处理器
  46. Thread.setDefaultUncaughtExceptionHandler(this);
  47. phone = new GetPhoneInfo(context);
  48. }
  49. /**
  50. * 当UncaughtException发生时会转入该函数来处理
  51. */
  52. @Override
  53. public void uncaughtException(Thread thread, Throwable ex) {
  54. if (!handleException(thread, ex) && mDefaultHandler != null) {
  55. // 如果用户没有处理则让系统默认的异常处理器来处理
  56. mDefaultHandler.uncaughtException(thread, ex);
  57. } else {
  58. try {
  59. Thread.sleep(3000);
  60. } catch (InterruptedException e) {
  61. Log.e(TGA, e.toString());
  62. }
  63. // 退出程序
  64. android.os.Process.killProcess(android.os.Process.myPid());
  65. System.exit(1);
  66. }
  67. }
  68. /**
  69. * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
  70. *
  71. * @param ex
  72. * @return true:如果处理了该异常信息;否则返回false.
  73. */
  74. private boolean handleException(Thread thread, Throwable ex) {
  75. if (ex == null) {
  76. return false;
  77. }
  78. // 使用Toast来显示异常信息
  79. new Thread() {
  80. @Override
  81. public void run() {
  82. Looper.prepare();
  83. ShowToast.show(mContext, "喵,很抱歉,程序出现异常,即将退出!",
  84. R.drawable.error_icon);
  85. Looper.loop();
  86. }
  87. }.start();
  88. // 把异常信息和设备信息上传到服务器
  89. subMitThreadAndDeviceInfo(mContext, thread, ex);
  90. return true;
  91. }
  92. // 提交信息到服务器
  93. public void subMitThreadAndDeviceInfo(Context ctx, Thread thread,
  94. Throwable ex) {
  95. // 当前用户的账号
  96. String Account = null;
  97. if (Config.getCachedAccount(ctx) != null) {
  98. Account = Config.getCachedAccount(ctx);
  99. } else {
  100. Account = "当前无用户登录";
  101. }
  102. // 手机设备的信息
  103. String PhoneModel = phone.PhoneModel;
  104. String PhoneVersion = phone.PhoneVersion;
  105. String PhoneResolution = phone.PhoneResolution;
  106. String ZcmVersion = phone.ZcmVersion;
  107. String AvailableRom = phone.AvailableRom;
  108. // 获取当前显示在界面上的Activity的路径加类名
  109. ActivityManager am = (ActivityManager) ctx
  110. .getSystemService(Context.ACTIVITY_SERVICE);
  111. ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
  112. // 异常信息加异常所在类的绝对路径
  113. final String content = "thread: " + thread + " , name: "
  114. + thread.getName() + ", id: " + thread.getId()
  115. + ", exception: " + ex + ", " + cn.getClassName();
  116. // 执行接口,把异常信息提交到服务器
  117. new SubmitConfigBugs(0, ctx, Account, PhoneModel, PhoneVersion,
  118. PhoneResolution, ZcmVersion, AvailableRom, content,
  119. new SubmitConfigBugs.SuccessCallback() {
  120. @Override
  121. public void onSuccess() {
  122. Log.e(TGA, content + "\n错误信息提交成功");
  123. }
  124. }, new SubmitConfigBugs.FailCallback() {
  125. @Override
  126. public void onFail() {
  127. Log.e(TGA, content + "\n错误信息提交失败");
  128. }
  129. });
  130. }
  131. }


(2)实体类:手机信息

  1. package com.x1.tools;
  2. import android.content.Context;
  3. import android.content.pm.PackageInfo;
  4. import android.content.pm.PackageManager;
  5. import android.os.Environment;
  6. import android.os.StatFs;
  7. import android.text.TextUtils;
  8. import android.view.Display;
  9. import android.view.WindowManager;
  10. /**
  11. * 获取当前手机的设备信息和当前软件的版本
  12. *
  13. * @author zengtao 2015年5月6日
  14. *
  15. *
  16. */
  17. public class GetPhoneInfo {
  18. private Context context;
  19. public String PhoneModel;
  20. public String PhoneVersion;
  21. public String PhoneResolution;
  22. public String ZcmVersion;
  23. public String AvailableRom;
  24. public GetPhoneInfo(Context context) {
  25. this.context = context;
  26. PhoneModel = android.os.Build.MODEL;
  27. PhoneVersion = android.os.Build.VERSION.RELEASE;
  28. PhoneResolution = getDisplayWAndH();
  29. ZcmVersion = getAppVersionName(this.context);
  30. AvailableRom = "ROM剩余存储空间: " + getAvailableInternalMemorySize() + "MB"
  31. + ",内置SDCard剩余存储空间: " + getAvailableExternalMemorySize() + "MB";
  32. }
  33. // 获取当前版本号
  34. private String getAppVersionName(Context context) {
  35. String versionName = "";
  36. try {
  37. PackageManager packageManager = context.getPackageManager();
  38. PackageInfo packageInfo = packageManager.getPackageInfo(
  39. "com.x1.ui", 0);
  40. versionName = packageInfo.versionName;
  41. if (TextUtils.isEmpty(versionName)) {
  42. return "";
  43. }
  44. } catch (Exception e) {
  45. e.printStackTrace();
  46. }
  47. return versionName;
  48. }
  49. // 获取屏幕分辨率
  50. @SuppressWarnings("deprecation")
  51. private String getDisplayWAndH() {
  52. WindowManager wm = (WindowManager) context
  53. .getSystemService(Context.WINDOW_SERVICE);
  54. Display display = wm.getDefaultDisplay();
  55. String string = "屏幕分辨率: " + display.getWidth() + "x"
  56. + display.getHeight();
  57. return string;
  58. }
  59. /**
  60. *
  61. * @return ROM存储路径
  62. */
  63. private String getInternalMemoryPath() {
  64. return Environment.getDataDirectory().getPath();
  65. }
  66. /**
  67. *
  68. * @return 内置sd卡路径
  69. */
  70. private String getExternalMemoryPath() {
  71. return Environment.getExternalStorageDirectory().getPath();
  72. }
  73. /**
  74. *
  75. * @param path
  76. * 文件路径
  77. * @return 文件路径的StatFs对象
  78. * @throws Exception
  79. * 路径为空或非法异常抛出
  80. */
  81. private StatFs getStatFs(String path) {
  82. try {
  83. return new StatFs(path);
  84. } catch (Exception e) {
  85. e.printStackTrace();
  86. }
  87. return null;
  88. }
  89. /**
  90. *
  91. * @param stat
  92. * 文件StatFs对象
  93. * @return 剩余存储空间的MB数
  94. *
  95. */
  96. @SuppressWarnings("deprecation")
  97. private float calculateSizeInMB(StatFs stat) {
  98. if (stat != null)
  99. return stat.getAvailableBlocks()
  100. * (stat.getBlockSize() / (1024f * 1024f));
  101. return 0.0f;
  102. }
  103. /**
  104. *
  105. * @return ROM剩余存储空间的MB数
  106. */
  107. private float getAvailableInternalMemorySize() {
  108. String path = getInternalMemoryPath();// 获取数据目录
  109. StatFs stat = getStatFs(path);
  110. return calculateSizeInMB(stat);
  111. }
  112. /**
  113. *
  114. * @return 内置SDCard剩余存储空间MB数
  115. */
  116. private float getAvailableExternalMemorySize() {
  117. String path = getExternalMemoryPath();// 获取数据目录
  118. StatFs stat = getStatFs(path);
  119. return calculateSizeInMB(stat);
  120. }
  121. }


四:总结

以上呢,就可以直接抓捕程序中未处理的异常,而且使得用户在系统自身开发崩溃的时候,不至于造成,直接挂了,所以,在程序中,做这样的处理是非常有必要的,在上面CrashHandlers有一个执行接口的处理,提交数据到服务器,这个是自身开发中所定义的接口,这个可以根据自己的想法实现,我在这个当中,是将手机提交的一些信息,和错误信息发送到服务器,而完成的,这样也可以让自己知道,是什么手机出错,有目的去处理,更好的维护自己的系统。


声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号