Android防崩溃处理技巧
简单介绍:
Android开发过程中,因为各种原因导致app崩溃的现象层出不穷,异常奔溃带来的用户体验及其差劲,尤其当一个小小的功能页面的问题导致app整体奔溃带来的操作感受极差,防止app崩溃,虽然不能从根本解决用户体验的基本问题,但可以在此基础上处理,并带来更好地错误交互处理方法。
程序中,可以捕捉到的异常,通常使用try...catch..finally来解决,但还存在一些我们没有捕捉到的异常,例如,使用控件不绑定,变量未初始化等,而捕捉这些由于疏忽而产生的异常则使用 UncaughtExceptionHandler对象来实现。
常见的异常奔溃带来的处理步骤:
1)将错误异常等记录到本地日志中
2)弹出弹窗,提醒用户出现bug,请用户配合上传错误日志
3)提醒用户出现bug的功能暂时不要使用,然后弹到主页面。
UncaughtExceptionHandler的封装(网上已经有人封装好了,直接参考写一下):
/**
* Created by Zhu Hao on 2018/2/7.
*/
/**
* 全局捕获异常信息
* 发生Uncaught异常时,由该类来接管程序
*/
public class CrashHandler implements UncaughtExceptionHandler {
private static final String TAG = "CrashHandler";
@SuppressLint("StaticFieldLeak")
private static CrashHandler instance ;
private Thread.UncaughtExceptionHandler mDefaultUEHandler ;
private Context mContext;
//格式化日期
@SuppressLint("SimpleDateFormat")
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private CrashHandler(){
//获取系统默认UncaughtException处理器
mDefaultUEHandler = Thread.getDefaultUncaughtExceptionHandler();
}
public static CrashHandler getInstance(){
synchronized (CrashHandler.class){
if (instance == null){
return new CrashHandler();
}
return instance;
}
}
public void init(Context context){
mContext = context;
//设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* 当UncaughExcept发生时会转入该函数来处理
* @param thread
* @param throwable
*/
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
Log.i(TAG, "uncaughtException: 先捕捉到");
if (AppParams.DEBUG_EX){
//调试的时候,记得将DEBUG_EX置成True,
Log.i(TAG, "uncaughtException: 被系统机制开始处理,app开始崩溃");
//交由系统默认的错误处理器来处理,也就是"崩溃报错"
mDefaultUEHandler.uncaughtException(thread,throwable);
}
if (handleException(throwable)){
Log.i(TAG, "uncaughtException: 运行到这里");
// showDialog(mContext);
//表示被自己写的handlerException处理了,进行收尾操作
// SystemClock.sleep(3000);
Log.i(TAG, "uncaughtException: CrashHandler处理了");
}else {
//自己的CrashHandler没有捕捉到异常,交由系统机制进行崩溃处理
mDefaultUEHandler.uncaughtException(thread,throwable);
}
Log.i(TAG, "uncaughtException: 后捕捉到");
}
/**
* 自定义错误处理,收集错误信息,发送错误报告等操作
* @param ex
* @return true:如果处理了该错误信息返回true,否则返回false
*/
private boolean handleException(final Throwable ex){
if (ex == null){
return false;
}
try {
Log.i(TAG, "handleException: 发现了个错误,处理中....");
new Thread(){
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, "发现个错误", Toast.LENGTH_SHORT).show();
Log.i(TAG, "run: " + ex.toString());
showDialog(mContext);
Looper.loop();
// showDialog(mContext);
}
}.start();
Log.i(TAG, "handleException: CrashHandler处理完成");
}catch (Exception e){
e.printStackTrace();
}
return true;
}
private void showDialog(Context context){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(context.getResources().getString(R.string.app_crashHandler_dialog_summary));
builder.setTitle(context.getResources().getString(R.string.app_crashHandler_dialog_title));
builder.setPositiveButton(context.getResources().getString(R.string.app_crashHandler_dialog_upload)
, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.i(TAG, "onClick: 上传错误日志");
dialog.dismiss();
}
});
builder.setNegativeButton(context.getResources().getString(R.string.app_crashHandler_dialog_reIndex)
, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Index.getInstance().switchFragment(AppParams.FragMenuList);
dialog.dismiss();
}
});
Dialog dialog=builder.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
}
}
其中,AppParams.DEBUG_EX 是封装的全局参数,调试时置成True,报错容易看到,不调试置成false,防止报错,生成错误日志。
Index.getInstance().switchFragment(AppParams.FragMenuList) 是封装的Fragment的切换方法。
使用方法:
在Application中初始化即可:
/**
* Created by Jason Zhu on 2017-08-21.
* Email: cloud_happy@163.com
*/
public class AIO extends Application {
private static AIO instance;
//用list保存每个Activity
private List mActivityList = new LinkedList();
private List mServiceList = new LinkedList();
public static AIO getInstance(){
if (null == instance){
instance = new AIO();
}
return instance;
}
@Override
public void onCreate() {
super.onCreate();
instance = this;
//这里使用即可
CrashHandler.getInstance().init(this);
}
public void AddActivityList(Activity activity){
mActivityList.add(activity);
}
public void AddServiceList(Service service ){
mServiceList.add(service);
}
public void Exit(){
try{
for (Activity activity : mActivityList){
if (null != activity){
Log.i("Application", "Exit: " + activity.getLocalClassName());
activity.finish();
}
}
for (Service service :mServiceList){
if (null != service){
service.stopSelf();
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
Handler mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
System.exit(0);
}
},200);
//
}
}
}
上一篇: Android开发_mDNS移植Android系统方案介绍
下一篇: 企业信息安全系统工程的构建