首页 > 代码库 > 【Android开发经验】我们要友好的告诉用户,程序要崩溃了
【Android开发经验】我们要友好的告诉用户,程序要崩溃了
转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992
虽然我们的程序在正式上线之前,都会经过严格的测试,从而保证程序的健壮性和良好的用户体验,但是,一个人的测试或者是几个人的测试团队,都不能和上万甚至数十万的用户相比。因此,前期刚上线的程序在用户手里被玩崩了,也是很常见的事,但是,如果我们不做特殊处理,系统自带的程序崩溃提示真的太吓人了,用户看到之后会不知所措,因此,我们需要一个解决方案,就是在程序即将崩溃的时候,给用户一个更加友好的提示,来告诉他,程序马上要崩溃了。
就像是下面这样:
这样是不是更加友好一点呢?
下面讲解如何实现。
如果要实现这种功能,我们需要关注的是Thread类里面的一个接口,UncaughtExceptionHandler,还有一个设置Thread.setDefaultUncaughtExceptionHandler(),这两个东西到底是干嘛的呢?
UncaughtExceptionHandler 这个接口是当Thread因为未被捕获的异常而要被终止的时候,会被调用的回调接口。
而Thread.setDefaultUncaughtExceptionHandler()这个方法,则是设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。
因此,如果我们想自己处理程序要崩溃时的处理逻辑,我们只需要实现UncaughtExceptionHandler接口,并调用Thread.setDefaultUncaughtExceptionHandler()设置即可。
下面是示例代码
首先,先给出上面效果图中的Activity的代码
package com.example.exceptiondemo; import android.app.Activity; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 注册默认的未捕捉异常处理类 Thread.setDefaultUncaughtExceptionHandler(AppException .getAppExceptionHandler()); AppManager.getAppManager().addActivity(this); } public void btn(View view) { // 除零错误,程序会崩溃 int c = 1 / 0; } }
在这段代码里面,我们故意写了一个会出现异常的操作,除零,因此只要点击按钮,程序就会崩溃。
下面,我们要自己实现接口,这里,我继承了Exception类。
package com.example.exceptiondemo; import java.lang.Thread.UncaughtExceptionHandler; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.os.Looper; import android.widget.Toast; /** * * @ClassName: com.example.exceptiondemo.AppException * @Description: 应用程序异常类:用于捕获异常 * @author zhaokaiqiang * @date 2014-11-2 下午10:06:49 * */ public class AppException extends Exception implements UncaughtExceptionHandler { private static final long serialVersionUID = -6262909398048670705L; private String message; private Thread.UncaughtExceptionHandler mDefaultHandler; private AppException() { super(); this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); } public AppException(String message, Exception excp) { super(message, excp); this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } /** * 获取APP异常崩溃处理对象 * * @param context * @return */ public static AppException getAppExceptionHandler() { return new AppException(); } @Override public void uncaughtException(Thread thread, Throwable ex) { if (!handleException(ex) && mDefaultHandler != null) { mDefaultHandler.uncaughtException(thread, ex); } } /** * 自定义异常处理 * * @param ex * @return true:处理了该异常信息;否则返回false */ private boolean handleException(Throwable ex) { if (ex == null) { return false; } final Activity activity = AppManager.getAppManager().currentActivity(); if (activity == null) { return false; } new Thread() { @Override public void run() { Looper.prepare(); Toast.makeText(activity, "程序要崩了", Toast.LENGTH_SHORT).show(); new AlertDialog.Builder(activity).setTitle("提示") .setCancelable(false).setMessage("亲,程序马上崩溃了...") .setNeutralButton("没关系", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { AppManager.getAppManager().exitApp(activity); } }).create().show(); Looper.loop(); } }.start(); return true; } }
实现借口之后,我们需要在uncaughtException()方法里面处理自己的逻辑,我在这里面弹出对话框提示用户程序崩溃,这样,就比较友好一些。在代码里面的AppManager类是一个Activity的管理类,下面是代码
package com.example.exceptiondemo; import java.util.Stack; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; /** * * @ClassName: net.oschina.app.AppManager * @Description: Activity管理类:用于管理Activity和退出程序 * @author zhaokaiqiang * @date 2014-11-2 上午11:27:55 * */ public class AppManager { private static Stack<Activity> activityStack; private static AppManager instance; private AppManager() { } /** * 单一实例 */ public static AppManager getAppManager() { if (instance == null) { instance = new AppManager(); } return instance; } /** * 添加Activity到堆栈 */ public void addActivity(Activity activity) { if (activityStack == null) { activityStack = new Stack<Activity>(); } activityStack.add(activity); } /** * 获取当前Activity(堆栈中最后一个压入的) */ public Activity currentActivity() { Activity activity = activityStack.lastElement(); return activity; } /** * 结束当前Activity(堆栈中最后一个压入的) */ public void finishActivity() { Activity activity = activityStack.lastElement(); finishActivity(activity); } /** * 结束指定的Activity */ public void finishActivity(Activity activity) { if (activity != null) { activityStack.remove(activity); activity.finish(); activity = null; } } /** * 结束指定类名的Activity */ public void finishActivity(Class<?> cls) { for (Activity activity : activityStack) { if (activity.getClass().equals(cls)) { finishActivity(activity); } } } /** * 结束所有Activity */ public void finishAllActivity() { for (int i = 0, size = activityStack.size(); i < size; i++) { if (null != activityStack.get(i)) { activityStack.get(i).finish(); } } activityStack.clear(); } /** * 退出应用程序 */ public void exitApp(Context context) { try { finishAllActivity(); ActivityManager activityMgr = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); activityMgr.killBackgroundProcesses(context.getPackageName()); System.exit(0); } catch (Exception e) { } } }
【Android开发经验】我们要友好的告诉用户,程序要崩溃了