0%

Android系统去掉ANR和app无响应的错误弹出框

最近在做广告发布终端,基于安卓开发的app,但是在系统或者其他原因会导致异常错误弹窗提示,所以本文旨在去掉这些异常弹窗,增加使用体验

Android7.1屏蔽掉弹出无响应对话框和已停止对话框
代码路径:
/frameworks/base/services/core/java/com/android/server/am/AppErrors.java

handleShowAppErrorUi()handleShowAnrUi() dialog.show()之前 添加包名的判断、过滤或者屏蔽掉弹窗显示即可
以下是实际修改的内容

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
void handleShowAppErrorUi(Message msg) {
AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
synchronized (mService) {
ProcessRecord proc = data.proc;
AppErrorResult res = data.result;
if (proc != null && proc.crashDialog != null) {
Slog.e(TAG, "App already has crash dialog: " + proc);
if (res != null) {
res.set(AppErrorDialog.ALREADY_SHOWING);
}
return;
}
boolean isBackground = (UserHandle.getAppId(proc.uid)
>= Process.FIRST_APPLICATION_UID
&& proc.pid != MY_PID);
for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) {
isBackground &= (proc.userId != userId);
}
if (isBackground && !showBackground) {
Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
if (res != null) {
res.set(AppErrorDialog.BACKGROUND_USER);
}
return;
}
final boolean crashSilenced = mAppsNotReportingCrashes != null &&
mAppsNotReportingCrashes.contains(proc.info.packageName);
if ((mService.canShowErrorDialogs() || showBackground) && !crashSilenced) {
proc.crashDialog = new AppErrorDialog(mContext, mService, data);
} else {
// The device is asleep, so just pretend that the user
// saw a crash dialog and hit "force quit".
if (res != null) {
res.set(AppErrorDialog.CANT_SHOW);
}
}
}
//增加包名过滤
if (data.proc.crashDialog != null && data.proc.info.packageName != null && data.proc.info.packageName.equals("com.wyw.videodemo")) {
return;
}
// If we've created a crash dialog, show it without the lock held
if (data.proc.crashDialog != null) {
//屏蔽此处所有crash弹窗不会显示
data.proc.crashDialog.show();
}
}

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
void handleShowAnrUi(Message msg) {
Dialog d = null;
synchronized (mService) {
HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
ProcessRecord proc = (ProcessRecord) data.get("app");
if (proc != null && proc.anrDialog != null) {
Slog.e(TAG, "App already has anr dialog: " + proc);
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
AppNotRespondingDialog.ALREADY_SHOWING);
return;
}

Intent intent = new Intent("android.intent.action.ANR");
if (!mService.mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
}
mService.broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);

boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
if (mService.canShowErrorDialogs() || showBackground) {
d = new AppNotRespondingDialog(mService,
mContext, proc, (ActivityRecord) data.get("activity"),
msg.arg1 != 0);
proc.anrDialog = d;
} else {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
AppNotRespondingDialog.CANT_SHOW);
// Just kill the app if there is no dialog to be shown.
mService.killAppAtUsersRequest(proc, null);
}
}
//增加包名过滤
if(d != null &&proc != null && proc.info.packageName.equals("com.wyw.videodemo")){
return;
}
// If we've created a crash dialog, show it without the lock held
if (d != null) {
//屏蔽此处所有crash弹窗不会显示
d.show();
}
}

Android 4.4 屏蔽掉弹出无响应对话框和已停止对话框

代码路径:
frameworks\base\services\java\com\android\server\am\ActivityManagerService.java
在ActivityManagerService.java中接收消息handleMessage中处理弹出对话框
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
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_ERROR_MSG: {
HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
synchronized (ActivityManagerService.this) {
ProcessRecord proc = (ProcessRecord)data.get("app");
AppErrorResult res = (AppErrorResult) data.get("result");
if (proc != null && proc.crashDialog != null) {
Slog.e(TAG, "App already has crash dialog: " + proc);
if (res != null) {
res.set(0);
}
return;
}
if (!showBackground && UserHandle.getAppId(proc.uid)
>= Process.FIRST_APPLICATION_UID && proc.userId != mCurrentUserId
&& proc.pid != MY_PID) {
Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
if (res != null) {
res.set(0);
}
return;
}
if (mShowDialogs && !mSleeping && !mShuttingDown) {
//显示已停止运行对话框
Dialog d = new AppErrorDialog(mContext,
ActivityManagerService.this, res, proc);
// d.show();
proc.crashDialog = d;
} else {
// The device is asleep, so just pretend that the user
// saw a crash dialog and hit "force quit".
if (res != null) {
res.set(0);
}
}
}

ensureBootCompleted();
} break;

2、屏蔽掉弹出无响应对话框

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
case SHOW_NOT_RESPONDING_MSG: {
synchronized (ActivityManagerService.this) {
HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
ProcessRecord proc = (ProcessRecord)data.get("app");
if (proc != null && proc.anrDialog != null) {
Slog.e(TAG, "App already has anr dialog: " + proc);
return;
}

Intent intent = new Intent("android.intent.action.ANR");
if (!mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
}
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);

if (mShowDialogs) {
//去掉无响应对话框
Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
mContext, proc, (ActivityRecord)data.get("activity"),
msg.arg1 != 0);
//d.show();
proc.anrDialog = d;
} else {
// Just kill the app if there is no dialog to be shown.
killAppAtUsersRequest(proc, null);
}
}

ensureBootCompleted();
} break;