【Android开发经验】我们要友好的告诉用户,程序要崩溃了

来源:互联网 发布:电脑怎么申请淘宝达人 编辑:程序博客网 时间:2024/05/16 11:50

原帖地址:http://blog.csdn.net/zhaokaiqiang1992


虽然我们的程序在正式上线之前,都会经过严格的测试,从而保证程序的健壮性和良好的用户体验,但是,一个人的测试或者是几个人的测试团队,都不能和上万甚至数十万的用户相比。因此,前期刚上线的程序在用户手里被玩崩了,也是很常见的事,但是,如果我们不做特殊处理,系统自带的程序崩溃提示真的太吓人了,用户看到之后会不知所措,因此,我们需要一个解决方案,就是在程序即将崩溃的时候,给用户一个更加友好的提示,来告诉他,程序马上要崩溃了。

    就像是下面这样:



     这样是不是更加友好一点呢?

    下面讲解如何实现。

     如果要实现这种功能,我们需要关注的是Thread类里面的一个接口,UncaughtExceptionHandler,还有一个设置Thread.setDefaultUncaughtExceptionHandler(),这两个东西到底是干嘛的呢?

    UncaughtExceptionHandler 这个接口是当Thread因为未被捕获的异常而要被终止的时候,会被调用的回调接口。

    而Thread.setDefaultUncaughtExceptionHandler()这个方法,则是设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。

    因此,如果我们想自己处理程序要崩溃时的处理逻辑,我们只需要实现UncaughtExceptionHandler接口,并调用Thread.setDefaultUncaughtExceptionHandler()设置即可。

    下面是示例代码

    首先,先给出上面效果图中的Activity的代码

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.example.exceptiondemo;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.View;  
  6.   
  7. public class MainActivity extends Activity {  
  8.   
  9.     @Override  
  10.     protected void onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.activity_main);  
  13.         // 注册默认的未捕捉异常处理类  
  14.         Thread.setDefaultUncaughtExceptionHandler(AppException  
  15.                 .getAppExceptionHandler());  
  16.         AppManager.getAppManager().addActivity(this);  
  17.   
  18.     }  
  19.   
  20.     public void btn(View view) {  
  21.         // 除零错误,程序会崩溃  
  22.         int c = 1 / 0;  
  23.     }  
  24.   
  25. }  

    在这段代码里面,我们故意写了一个会出现异常的操作,除零,因此只要点击按钮,程序就会崩溃。

    下面,我们要自己实现接口,这里,我继承了Exception类。

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.example.exceptiondemo;  
  2.   
  3. import java.lang.Thread.UncaughtExceptionHandler;  
  4.   
  5. import android.app.Activity;  
  6. import android.app.AlertDialog;  
  7. import android.content.DialogInterface;  
  8. import android.content.DialogInterface.OnClickListener;  
  9. import android.os.Looper;  
  10. import android.widget.Toast;  
  11.   
  12. /** 
  13.  *  
  14.  * @ClassName: com.example.exceptiondemo.AppException 
  15.  * @Description: 应用程序异常类:用于捕获异常 
  16.  * @author zhaokaiqiang 
  17.  * @date 2014-11-2 下午10:06:49 
  18.  *  
  19.  */  
  20.   
  21. public class AppException extends Exception implements UncaughtExceptionHandler {  
  22.   
  23.     private static final long serialVersionUID = -6262909398048670705L;  
  24.   
  25.     private String message;  
  26.   
  27.     private Thread.UncaughtExceptionHandler mDefaultHandler;  
  28.   
  29.     private AppException() {  
  30.         super();  
  31.         this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();  
  32.     }  
  33.   
  34.     public AppException(String message, Exception excp) {  
  35.         super(message, excp);  
  36.         this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();  
  37.     }  
  38.   
  39.     public String getMessage() {  
  40.         return message;  
  41.     }  
  42.   
  43.     public void setMessage(String message) {  
  44.         this.message = message;  
  45.     }  
  46.   
  47.     /** 
  48.      * 获取APP异常崩溃处理对象 
  49.      *  
  50.      * @param context 
  51.      * @return 
  52.      */  
  53.     public static AppException getAppExceptionHandler() {  
  54.         return new AppException();  
  55.     }  
  56.   
  57.     @Override  
  58.     public void uncaughtException(Thread thread, Throwable ex) {  
  59.   
  60.         if (!handleException(ex) && mDefaultHandler != null) {  
  61.             mDefaultHandler.uncaughtException(thread, ex);  
  62.         }  
  63.   
  64.     }  
  65.   
  66.     /** 
  67.      * 自定义异常处理 
  68.      *  
  69.      * @param ex 
  70.      * @return true:处理了该异常信息;否则返回false 
  71.      */  
  72.     private boolean handleException(Throwable ex) {  
  73.         if (ex == null) {  
  74.             return false;  
  75.         }  
  76.   
  77.         final Activity activity = AppManager.getAppManager().currentActivity();  
  78.   
  79.         if (activity == null) {  
  80.             return false;  
  81.         }  
  82.   
  83.         new Thread() {  
  84.             @Override  
  85.             public void run() {  
  86.                 Looper.prepare();  
  87.                 Toast.makeText(activity, "程序要崩了", Toast.LENGTH_SHORT).show();  
  88.                 new AlertDialog.Builder(activity).setTitle("提示")  
  89.                         .setCancelable(false).setMessage("亲,程序马上崩溃了...")  
  90.                         .setNeutralButton("没关系"new OnClickListener() {  
  91.                             @Override  
  92.                             public void onClick(DialogInterface dialog,  
  93.                                     int which) {  
  94.                                 AppManager.getAppManager().exitApp(activity);  
  95.                             }  
  96.                         }).create().show();  
  97.                 Looper.loop();  
  98.             }  
  99.         }.start();  
  100.   
  101.         return true;  
  102.     }  
  103.   
  104. }  

    实现借口之后,我们需要在uncaughtException()方法里面处理自己的逻辑,我在这里面弹出对话框提示用户程序崩溃,这样,就比较友好一些。在代码里面的AppManager类是一个Activity的管理类,下面是代码

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.example.exceptiondemo;  
  2.   
  3. import java.util.Stack;  
  4.   
  5. import android.app.Activity;  
  6. import android.app.ActivityManager;  
  7. import android.content.Context;  
  8.   
  9. /** 
  10.  *  
  11.  * @ClassName: net.oschina.app.AppManager 
  12.  * @Description: Activity管理类:用于管理Activity和退出程序 
  13.  * @author zhaokaiqiang 
  14.  * @date 2014-11-2 上午11:27:55 
  15.  *  
  16.  */  
  17. public class AppManager {  
  18.   
  19.     private static Stack<Activity> activityStack;  
  20.     private static AppManager instance;  
  21.   
  22.     private AppManager() {  
  23.     }  
  24.   
  25.     /** 
  26.      * 单一实例 
  27.      */  
  28.     public static AppManager getAppManager() {  
  29.         if (instance == null) {  
  30.             instance = new AppManager();  
  31.         }  
  32.         return instance;  
  33.     }  
  34.   
  35.     /** 
  36.      * 添加Activity到堆栈 
  37.      */  
  38.     public void addActivity(Activity activity) {  
  39.         if (activityStack == null) {  
  40.             activityStack = new Stack<Activity>();  
  41.         }  
  42.         activityStack.add(activity);  
  43.     }  
  44.   
  45.     /** 
  46.      * 获取当前Activity(堆栈中最后一个压入的) 
  47.      */  
  48.     public Activity currentActivity() {  
  49.         Activity activity = activityStack.lastElement();  
  50.         return activity;  
  51.     }  
  52.   
  53.     /** 
  54.      * 结束当前Activity(堆栈中最后一个压入的) 
  55.      */  
  56.     public void finishActivity() {  
  57.         Activity activity = activityStack.lastElement();  
  58.         finishActivity(activity);  
  59.     }  
  60.   
  61.     /** 
  62.      * 结束指定的Activity 
  63.      */  
  64.     public void finishActivity(Activity activity) {  
  65.         if (activity != null) {  
  66.             activityStack.remove(activity);  
  67.             activity.finish();  
  68.             activity = null;  
  69.         }  
  70.     }  
  71.   
  72.     /** 
  73.      * 结束指定类名的Activity 
  74.      */  
  75.     public void finishActivity(Class<?> cls) {  
  76.         for (Activity activity : activityStack) {  
  77.             if (activity.getClass().equals(cls)) {  
  78.                 finishActivity(activity);  
  79.             }  
  80.         }  
  81.     }  
  82.   
  83.     /** 
  84.      * 结束所有Activity 
  85.      */  
  86.     public void finishAllActivity() {  
  87.         for (int i = 0, size = activityStack.size(); i < size; i++) {  
  88.             if (null != activityStack.get(i)) {  
  89.                 activityStack.get(i).finish();  
  90.             }  
  91.         }  
  92.         activityStack.clear();  
  93.     }  
  94.   
  95.     /** 
  96.      * 退出应用程序 
  97.      */  
  98.     public void exitApp(Context context) {  
  99.         try {  
  100.             finishAllActivity();  
  101.             ActivityManager activityMgr = (ActivityManager) context  
  102.                     .getSystemService(Context.ACTIVITY_SERVICE);  
  103.             activityMgr.killBackgroundProcesses(context.getPackageName());  
  104.             System.exit(0);  
  105.         } catch (Exception e) {  
  106.         }  
  107.     }  
  108. }  

    Demo下载地址:https://github.com/ZhaoKaiQiang/ExceptionDemo


自我感觉放在application里面会更好一些..

package com.example.testuncaultexception;import android.app.Application;import android.content.Context;public class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();Thread.setDefaultUncaughtExceptionHandler(AppException.getAppExceptionHandler());}}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 耳屎突然变湿该怎么办 小孩有耳屎好硬怎么办 小孩的耳屎深硬怎么办 1岁宝宝喉咙发炎怎么办 牙旁边的肉疼怎么办 鼻头软骨捏的痛怎么办 耳洞发炎肿了怎么办 一上火耳朵就疼怎么办 耳朵像隔了层膜怎么办 感冒引起的耳闷怎么办 5岁儿童视力0.6怎么办 柯基耳朵不立怎么办 宝宝一惊一乍睡觉不踏实怎么办 新婴儿睡觉不踏实怎么办 耳朵里面疼肿了怎么办 生出来的孩子是畸形怎么办 二胎生了缺陷儿怎么办 扣完肚脐眼后疼怎么办 刚出生的婴儿屁股红怎么办 狗狗耳朵流血了怎么办 狗狗不让掏耳朵怎么办 下巴总是反复长脓包怎么办 不胖但有双下巴怎么办 早上起床眼肿了怎么办 小孩鼻梁很塌的怎么办 17岁鼻子是塌的,怎么办 鼻子又塌又翘怎么办 戴眼镜鼻子塌了怎么办 耳朵里长了粉刺怎么办 耳洞太大了怎么办变小 天生嘴唇厚又大怎么办 上嘴唇太厚怎么办还翘 20岁欠债5万怎么办 脑袋撞了个包怎么办 交通事故对方全责但不赔偿怎么办 人格分列症的症状怎么办 子宫肌瘤月经量多怎么办 卵泡长得太慢怎么办 后期卵泡长得慢怎么办 促排卵泡长得慢怎么办 子宫内膜薄要怎么办啊