欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android防崩溃处理技巧

程序员文章站 2022-05-09 20:52:14
简单介绍: Android开发过程中,因为各种原因导致app崩溃的现象层出不穷,异常奔溃带来的用户体验及其差劲,尤其当一个小小的功能页面的问题导致app整体奔溃带来的操作感受极差...

简单介绍:

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);

//

}

}

}