Android去除烦人的默认闪退Dialog
安卓应用闪退后总会出现一个“抱歉,app已经停止运行”的弹窗,这样的用户体验并不好。很多大厂的app都去除了这个弹窗,因此本文主要介绍如何去除默认闪退弹窗,以及在闪退时做一些必要的善后工作。
uncaughtexceptionhandler
uncaughtexceptionhandler能够在thread遇到未catch住的exception而终止前做一些善后工作。但是它无法阻止线程停止运行,线程最后还是要退出。
thread.setdefaultuncaughtexceptionhandler(new thread.uncaughtexceptionhandler() { @override public void uncaughtexception(thread thread, throwable ex) { system.exit(1); } });
去除dialog
android系统默认设置了一个uncaughtexceptionhandler,而弹出闪退弹窗的工作就是在这个handler做的。所以如果要去除弹窗,只要实现一个uncaughtexceptionhandler并替换掉系统默认的就可以了,代码如下。
public class app extends application { @override public void oncreate() { super.oncreate(); thread.setdefaultuncaughtexceptionhandler(new myuncaughtexceptionhandler()); } class myuncaughtexceptionhandler implements thread.uncaughtexceptionhandler{ @override public void uncaughtexception(thread thread, throwable ex) { ex.printstacktrace(); // do some work here android.os.process.killprocess(android.os.process.mypid()); system.exit(1); } } }
以上的替换uncaughtexceptionhandler的工作是在application中统一做的,当然你也可以在每一个activity中做。对于单个activity还好,当activity很多的时候就必需实现一个baseactivity,在baseactivity中替换,其它activity要集成baseactivity。
必要的善后工作
为了处理闪退,提升用户体验,有必要做一些善后工作,主要有几条罗列如下:
异常上报
可以采用邮件或者通过服务器接口上传的方式。两者各有优缺点,邮件方式开发简单,但需要用户额外操作,用户体验较差。如果用上传服务器方式,因为在uncaughtexceptionhandler中不能打开一个新的线程,所以只能同步请求,在网络情况不好的时候花费时间会较长而阻塞运行。也可能因为网络原因而上报失败。当然总体下来还是上传服务器好一点。具体实现留给读者。
记录日志
将闪退信息存储到文件系统中。不能存到sharedpreferences中,因为打开sp需要使用一个新的线程(android内部实现),而这在uncaughtexceptionhandler中,这是不被允许的。
闪退三次清除数据
很多时候是由于后台返回数据错误导致的闪退。如果这些数据被缓存下来,那么用户即使再次打开还是会发生闪退,这时候就只能通过重装或者清除数据的方式才能解决闪退问题,用户体验十分不好。所以在多次闪退后自动清除缓存数据十分必要。具体实现可以参考我的另一篇博客android实现多次闪退清除数据。不过该博客中使用的是acra,一个对uncaughtexceptionhandler再次封装的开源项目,读者可以将acra替换为uncaughtexceptionhandler来实现。
重新打开app
可以在uncaughtexceptionhandler中重新打开app或者弹出自定义弹窗。
class myuncaughtexceptionhandler implements thread.uncaughtexceptionhandler{ @override public void uncaughtexception(thread thread, throwable ex) { ex.printstacktrace(); intent intent = new intent(app.this, mainactivity.class); intent.setflags(intent.flag_activity_new_task); app.this.startactivity(intent); android.os.process.killprocess(android.os.process.mypid()); system.exit(1); } }
注意setflags这一步是必需的,因为使用的context是app的context,所以必需打开一个新的任务队列,否则打开activity无法生效,如果你替换handler是在activity做的,拿到的context是activity的context,则无需这一步。
注意事项
最主要的注意点我之前已经提到,不要在uncaughtexceptionhandler中新开一个线程,会抛出异常。
以上就是本文的全部内容,希望对大家的学习有所帮助。
上一篇: 牛顿迭代法求平方根