分享

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

 花荆 2015-05-28

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

作者:  发布日期:2014-11-03 21:27:38
0
Tag标签:经验  程序  用户  
  •  

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

    就像是下面这样:

    \

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

    下面讲解如何实现。

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

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

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

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

    下面是示例代码

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

     

    01.package com.example.exceptiondemo;
    02. 
    03.import android.app.Activity;
    04.import android.os.Bundle;
    05.import android.view.View;
    06. 
    07.public class MainActivity extends Activity {
    08. 
    09.@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类。

     

    001.package com.example.exceptiondemo;
    002. 
    003.import java.lang.Thread.UncaughtExceptionHandler;
    004. 
    005.import android.app.Activity;
    006.import android.app.AlertDialog;
    007.import android.content.DialogInterface;
    008.import android.content.DialogInterface.OnClickListener;
    009.import android.os.Looper;
    010.import android.widget.Toast;
    011. 
    012./**
    013.*
    014.* @ClassName: com.example.exceptiondemo.AppException
    015.* @Description: 应用程序异常类:用于捕获异常
    016.* @author zhaokaiqiang
    017.* @date 2014-11-2 下午10:06:49
    018.*
    019.*/
    020. 
    021.public class AppException extends Exception implements UncaughtExceptionHandler {
    022. 
    023.private static final long serialVersionUID = -6262909398048670705L;
    024. 
    025.private String message;
    026. 
    027.private Thread.UncaughtExceptionHandler mDefaultHandler;
    028. 
    029.private AppException() {
    030.super();
    031.this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
    032.}
    033. 
    034.public AppException(String message, Exception excp) {
    035.super(message, excp);
    036.this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
    037.}
    038. 
    039.public String getMessage() {
    040.return message;
    041.}
    042. 
    043.public void setMessage(String message) {
    044.this.message = message;
    045.}
    046. 
    047./**
    048.* 获取APP异常崩溃处理对象
    049.*
    050.* @param context
    051.* @return
    052.*/
    053.public static AppException getAppExceptionHandler() {
    054.return new AppException();
    055.}
    056. 
    057.@Override
    058.public void uncaughtException(Thread thread, Throwable ex) {
    059. 
    060.if (!handleException(ex) && mDefaultHandler != null) {
    061.mDefaultHandler.uncaughtException(thread, ex);
    062.}
    063. 
    064.}
    065. 
    066./**
    067.* 自定义异常处理
    068.*
    069.* @param ex
    070.* @return true:处理了该异常信息;否则返回false
    071.*/
    072.private boolean handleException(Throwable ex) {
    073.if (ex == null) {
    074.return false;
    075.}
    076. 
    077.final Activity activity = AppManager.getAppManager().currentActivity();
    078. 
    079.if (activity == null) {
    080.return false;
    081.}
    082. 
    083.new Thread() {
    084.@Override
    085.public void run() {
    086.Looper.prepare();
    087.Toast.makeText(activity, "程序要崩了", Toast.LENGTH_SHORT).show();
    088.new AlertDialog.Builder(activity).setTitle("提示")
    089..setCancelable(false).setMessage("亲,程序马上崩溃了...")
    090..setNeutralButton("没关系", new OnClickListener() {
    091.@Override
    092.public void onClick(DialogInterface dialog,
    093.int which) {
    094.AppManager.getAppManager().exitApp(activity);
    095.}
    096.}).create().show();
    097.Looper.loop();
    098.}
    099.}.start();
    100. 
    101.return true;
    102.}
    103. 
    104.}

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

     

     

    001.package com.example.exceptiondemo;
    002. 
    003.import java.util.Stack;
    004. 
    005.import android.app.Activity;
    006.import android.app.ActivityManager;
    007.import android.content.Context;
    008. 
    009./**
    010.*
    011.* @ClassName: net.oschina.app.AppManager
    012.* @Description: Activity管理类:用于管理Activity和退出程序
    013.* @author zhaokaiqiang
    014.* @date 2014-11-2 上午11:27:55
    015.*
    016.*/
    017.public class AppManager {
    018. 
    019.private static Stack<Activity> activityStack;
    020.private static AppManager instance;
    021. 
    022.private AppManager() {
    023.}
    024. 
    025./**
    026.* 单一实例
    027.*/
    028.public static AppManager getAppManager() {
    029.if (instance == null) {
    030.instance = new AppManager();
    031.}
    032.return instance;
    033.}
    034. 
    035./**
    036.* 添加Activity到堆栈
    037.*/
    038.public void addActivity(Activity activity) {
    039.if (activityStack == null) {
    040.activityStack = new Stack<Activity>();
    041.}
    042.activityStack.add(activity);
    043.}
    044. 
    045./**
    046.* 获取当前Activity(堆栈中最后一个压入的)
    047.*/
    048.public Activity currentActivity() {
    049.Activity activity = activityStack.lastElement();
    050.return activity;
    051.}
    052. 
    053./**
    054.* 结束当前Activity(堆栈中最后一个压入的)
    055.*/
    056.public void finishActivity() {
    057.Activity activity = activityStack.lastElement();
    058.finishActivity(activity);
    059.}
    060. 
    061./**
    062.* 结束指定的Activity
    063.*/
    064.public void finishActivity(Activity activity) {
    065.if (activity != null) {
    066.activityStack.remove(activity);
    067.activity.finish();
    068.activity = null;
    069.}
    070.}
    071. 
    072./**
    073.* 结束指定类名的Activity
    074.*/
    075.public void finishActivity(Class<?> cls) {
    076.for (Activity activity : activityStack) {
    077.if (activity.getClass().equals(cls)) {
    078.finishActivity(activity);
    079.}
    080.}
    081.}
    082. 
    083./**
    084.* 结束所有Activity
    085.*/
    086.public void finishAllActivity() {
    087.for (int i = 0, size = activityStack.size(); i < size; i++) {
    088.if (null != activityStack.get(i)) {
    089.activityStack.get(i).finish();
    090.}
    091.}
    092.activityStack.clear();
    093.}
    094. 
    095./**
    096.* 退出应用程序
    097.*/
    098.public void exitApp(Context context) {
    099.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

    出处:http://blog.csdn.net/zhaokaiqiang1992

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多