版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shankezh/article/details/79332004
简单介绍:
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: [email protected]
*/
public class
AIO
extends
Application {
private static
AIO
instance
;
//用list保存每个Activity
private
List<Activity>
mActivityList
=
new
LinkedList<Activity>();
private
List<Service>
mServiceList
=
new
LinkedList<Service>();
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
);
//
}
}
}
参考来源: