Android去除烦人的默认闪退Dialog
作者:lijiao 发布时间:2022-07-16 19:56:14
安卓应用闪退后总会出现一个“抱歉,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中新开一个线程,会抛出异常。


猜你喜欢
- 本文实例为大家分享了java自定义异常打印内容的具体代码,供大家参考,具体内容如下背景:在开发中,我们可能会使用到自定义异常,但是,这个自定
- 数组实现Java 自定义Queue队列及应用Java 自定义队列Queue:队列的抽象数据类型就是一个容器,其中的对象排成一个序列,我们只能
- 一、定义责任链模式(Chain of Responsibility Pattern):避免将一个请求的发送者与接受者耦合在一起,让多个对象都
- SUM映射问题当我们根据类别进行统计,返回的数据类型为HashMap<String,Object>,获取数值类型,容易报java
- 1、三元运算符:class Program {  
- 本文实例为大家分享了java实现短信验证码5分钟有效时间,供大家参考,具体内容如下实现一个发送短信验证码的请求,要求5分钟之内重复请求,返回
- 前言之所以会有这篇文章,是因为公司的开发环境比较老,寻找一些jar包的时候总是会纠结对应的编译版本,感觉很麻烦,所以写了一个工具类用于读取c
- 以下是测试代码:新建一个classlibrary,包含两个类class1和class2,这两个类中分别有一个方法,都是返回一个字符串,代码如
- 非Web程序 1.AppDomain.CurrentDomain.BaseDirectory 2.Environment.CurrentDi
- SpringBoot 2.1.4 错误处理机制springboot的自动配置中帮我们配置了相关的错误处理组件,例如访问一个不存在的页面,就会
- 泛型概述我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进
- 前言XML文件是一种常用的文件格式,例如WinForm里面的app.config以及Web程序中的web.config文件,还有许多重要的场
- Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全
- 本文实例为大家分享了swing登录注册界面展示的具体代码,供大家参考,具体内容如下开发环境:Eclipse Neon.3 Release (
- 一、泛型的概念1.1 基础案例泛型在Java中的应用非常广泛,最常见则是在集合容器中,先看下基础用法:public class Generi
- 一般在web应用中,对客户端提交上来的图片肯定需要进行压缩的。尤其是比较大的图片,如果不经过压缩会导致页面变的很大,打开速度比较慢,当然了如
- 概述在JDK 1.8里,可以使用如下代码获取List元素对象中某个属性的列表。package test;import java.util.A
- 目录课设要求相关知识点1.服务端能够看到所有在线用户2.服务端能够强制用户下线3.客户端能够看到所有在线用户4.客户端要求能够向某个用户发送
- 样例 近期要做一个含有两个tab切换页面,两个页面有公共的描述信息区
- 本文实例讲述了C#使用ToUpper()与ToLower()方法将字符串进行大小写转换的方法。分享给大家供大家参考。具体分析如下:C#通过T