Android13 屏蔽ANR和Crash弹窗
2024-09-01 / 龙之叶   

前言

Android系统在应用发生Crash/ANR的时候,总会弹出一个提示对话框,但是现在部分客户不想要这样的对话框,要求移除

一、Application Crash

表现: 程序崩溃或闪退,界面上通常会出现“应用已停止运行”的提示。

常见原因(Java异常):

错误类型 详细描述
NullPointerException 尝试在需要对象的地方使用了null。
SQLException 数据库操作错误,如SQL语句错误、数据库连接问题等。
ClassCastException 尝试将对象强制转换为不是其实例的子类。
NumberFormatException 将字符串转换为数字时格式不正确。
ClassNotFoundException 尝试加载的类在类路径中找不到。
ArithmeticException 数学运算错误,如除以零。
ArrayIndexOutOfBoundsException 数组索引越界。
IllegalArgumentException 向方法传递了非法或不适当的参数。
IllegalAccessException 尝试访问或修改类的字段,但当前方法没有足够的访问权限。
ArrayStoreException 试图将错误类型的对象存储到数组中。

Native Crash(C++层):

Native Crash发生在C++代码层,Java层难以直接捕获错误信息,通常表现为应用闪退。可通过Monkey测试等自动化测试工具进行监控。

具体原因:

  • 设备碎片化:不同设备间的兼容性问题。
  • 网络问题:带宽不足、网络切换等。
  • 内存管理:内存泄漏、非授权内存访问等。
  • 用户负载:高并发用户导致的资源竞争。
  • 代码错误:空指针访问、非法指令执行等。
  • 第三方服务:如广告插件或第三方库的不稳定。

测试中如何关注:

  • 界面操作验证:确保所有按钮、控件操作有效,响应正确。
  • 负载测试:通过自动化工具进行长时间或高负载测试,暴露潜在问题。
  • 重复操作测试:多次重复相同操作,检查是否出现崩溃。
  • 异常输入测试:对输入框进行非标准输入,检查应用的容错能力。

解决方法:

  • 查看日志文件中的am_crash相关条目,定位崩溃点。
  • 根据日志中的堆栈跟踪,分析并修复代码问题。

二、ANR(Application Not Responding)

表现: 应用无响应,用户界面卡住,系统弹出等待或强制关闭的对话框。

对应用的影响:

  • 用户体验差,可能导致用户流失。
  • 操作中断,可能造成数据丢失。

产生原因:

  • 主线程阻塞:UI线程在5秒内未响应输入事件。
  • BroadcastReceiver超时:未在10秒内完成处理并返回。

根本原因:

  • 主线程执行了耗时的IO操作(如数据库读写、网络请求)。
  • CPU资源被其他应用或线程占用,导致主线程得不到足够的时间片。

测试中如何关注:

  • 耗时操作监控:关注上传大文件、保存复杂数据等操作的响应时间。
  • 网络压力测试:在网络状况不佳或变化时测试应用稳定性。
  • Monkey测试:通过随机事件生成器模拟用户操作,检测ANR问题。
  • 内存和CPU监控:在多任务、多线程场景下监测资源使用情况。

解决方法:

  • 在log文件夹中搜索am_anr或activitymanager: ANR,查找ANR日志。
  • 分析data_app_anr@xxx.txt文件中的异常堆栈,特别是主线程(main prio=5 tid=1)的阻塞情况。
  • 根据日志信息,优化代码,避免在主线程中执行耗时操作,或使用异步编程模型处理耗时任务。

代码示例

在常规开发中,经常遇到手机性能较低,以上优化方法提升不大的情况下,建议直接屏蔽弹窗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
diff --git a/frameworks/base/services/core/java/com/android/server/am/AppErrors.java b/frameworks/base/services/core/java/com/android/server/am/AppErrors.java
index 6d56454ede0..dedf694d9aa 100644
--- a/frameworks/base/services/core/java/com/android/server/am/AppErrors.java
+++ b/frameworks/base/services/core/java/com/android/server/am/AppErrors.java
@@ -142,6 +142,9 @@ class AppErrors {
*/
private final Object mBadProcessLock = new Object();

+ // Create by yeruilai 2024-8-29 15:57:56 Block ANR and Crash error dialogs
+ private static final boolean mShowDialog = !Build.IS_USER;
+
AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog) {
context.assertRuntimeOverlayThemable();
mService = service;
@@ -1048,7 +1051,11 @@ class AppErrors {
&& !crashSilenced && !shouldThottle
&& (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId);
- errState.getDialogController().showCrashDialogs(data);
+ // Create by yeruilai 2024-8-29 15:57:56 Block ANR and Crash error dialogs
+ android.util.Log.d(TAG,"yeruilai:AppErrors:showCrashDialogs:mShowDialog=" + mShowDialog);
+ if(mShowDialog) {
+ errState.getDialogController().showCrashDialogs(data);
+ }
if (!proc.isolated) {
mProcessCrashShowDialogTimes.put(proc.processName, proc.uid, now);
}
@@ -1099,7 +1106,11 @@ class AppErrors {
if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
AnrController anrController = errState.getDialogController().getAnrController();
if (anrController == null) {
- errState.getDialogController().showAnrDialogs(data);
+ // Create by yeruilai 2024-8-29 15:57:56 Block ANR and Crash error dialogs
+ android.util.Log.d(TAG,"yeruilai:AppErrors:showAnrDialogs:mShowDialog=" + mShowDialog);
+ if(mShowDialog) {
+ errState.getDialogController().showAnrDialogs(data);
+ }
} else {
String packageName = proc.info.packageName;
int uid = proc.info.uid;
@@ -1108,7 +1119,11 @@ class AppErrors {
if (showDialog) {
Slog.d(TAG, "ANR delay completed. Showing ANR dialog for package: "
+ packageName);
- errState.getDialogController().showAnrDialogs(data);
+ // Create by yeruilai 2024-8-29 15:57:56 Block ANR and Crash error dialogs
+ android.util.Log.d(TAG,"yeruilai:AppErrors:showAnrDialogs:mShowDialog=" + mShowDialog);
+ if(mShowDialog) {
+ errState.getDialogController().showAnrDialogs(data);
+ }
} else {
Slog.d(TAG, "ANR delay completed. Cancelling ANR dialog for package: "
+ packageName);

本文链接:
http://longzhiye.top/2024/09/01/2024-09-01/