IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> ANR 弹窗的显示原理 -> 正文阅读

[移动开发]ANR 弹窗的显示原理

作者:template-box
  1. BroadCastQueue TimeOut: 未在规定时间内未处理完广播:前台广播 10s 内, 后台 60s 内

  2. ContentProvider TimeOut: ?publish 在 10s 内没有完成

  3. Input Dispatching timeout: ?5s 内未响应键盘输入、触摸屏幕等事件

ANR 的根本原因是:应用未在规定的时间内处理 AMS 指定的任务才会 ANR。

所以 Service 未在指定时间内执行完成而且非主进程的 Service 仍然需要通过 AMS 进行通信。这也能说明一定会产生 ANR 的。

实验:

===

理论上是会,那我们就写个小 demo 来试一下。

写一个 Service:

class NoZuoNoDieService: Service() {

override fun onBind(intent: Intent?): IBinder? {

return null

}

override fun onCreate() {

super.onCreate()

// 小睡会模拟耗时

Thread.sleep(21_000)

}

}

然后在 AndroidManifest 里声明在独立进程

<service

android:name=".service.NoZuoNoDieService"

android:process=":whatever"

/>

最后我们把这个 Service 调起来作死

startService(Intent(this, NoZuoNoDieService::class.java))

应用并没有 ANR 弹窗,不过 logcat 有 ANR 相关信息,看一下 trace 文件:

----- pid 14608 at 2021-03-23 19:56:20 -----

Cmd line: demo.com.sam.demofactory:whatever

… 省略无关信息

“main” prio=5 tid=1 Sleeping

| group=“main” sCount=1 dsCount=0 flags=1 obj=0x73f13a80 self=0x78e7cc2a00

| sysTid=14608 nice=0 cgrp=default sched=0/0 handle=0x796c96d9a8

| state=S schedstat=( 57816925 3067496 80 ) utm=2 stm=3 core=4 HZ=100

| stack=0x7fe1d03000-0x7fe1d05000 stackSize=8MB

| held mutexes=

at java.lang.Thread.sleep(Native method)

  • sleeping on <0x0a71f3e8> (a java.lang.Object)

at java.lang.Thread.sleep(Thread.java:373)

  • locked <0x0a71f3e8> (a java.lang.Object)

at java.lang.Thread.sleep(Thread.java:314)

at demo.com.sam.demofactory.service.NoZuoNoDieService.onCreate(NoZuoNoDieService.kt:15)

at android.app.ActivityThread.handleCreateService(ActivityThread.java:3426)

at android.app.ActivityThread.-wrap4(ActivityThread.java:-1)

at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1744)

at android.os.Handler.dispatchMessage(Handler.java:106)

at android.os.Looper.loop(Looper.java:171)

at android.app.ActivityThread.main(ActivityThread.java:6611)

at java.lang.reflect.Method.invoke(Native method)

at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

ANR 弹窗的显示原理

===========

我们来看一下这个没有弹窗的 ANR 是怎么发生的

首先来复习一下?说一说 Service 的启动流程

AMS 真正去启动 Service 调用的是 ActiveServices.realStartServiceLocked 方法:

// API 29 com.android.server.am.ActiveServices

private final void realStartServiceLocked(ServiceRecord r,

ProcessRecord app, boolean execInFg) throws RemoteException {

bumpServiceExecutingLocked(r, execInFg, “create”);

}

private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {

scheduleServiceTimeoutLocked(r.app);

}

// 通过 Handler 延时发一条消息,延时时间则为 Service 触发的 ANR 时长

// SERVICE_TIMEOUT = 20*1000

// SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

void scheduleServiceTimeoutLocked(ProcessRecord proc) {

if (proc.executingServices.size() == 0 || proc.thread == null) {

return;

}

Message msg = mAm.mHandler.obtainMessage(

ActivityManagerService.SERVICE_TIMEOUT_MSG);

msg.obj = proc;

mAm.mHandler.sendMessageDelayed(msg,

proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);

}

如果 Service 在规定时间内启动完成,则这个消息会被 remove 掉,我们今天要看一下超时之后,收到这个消息是怎么处理的。

// com.android.server.am.ActivityManagerService.MainHandler

final class MainHandler extends Handler {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case SERVICE_TIMEOUT_MSG: {

mServices.serviceTimeout((ProcessRecord)msg.obj);

} break;

}

}

mServices 是 ActiveServices:

// com.android.server.am.ActiveServices#serviceTimeout

void serviceTimeout(ProcessRecord proc) {

if (timeout != null && mAm.mProcessList.mLruProcesses.contains(proc)) {

Slog.w(TAG, "Timeout executing service: " + timeout);

mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);

mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);

anrMessage = "executing service " + timeout.shortInstanceName;

}

if (anrMessage != null) {

proc.appNotResponding(null, null, null, null, false, anrMessage);

}

}

appNotResponding 就是最终处理 ANR 逻辑的代码了

// com.android.server.am.ProcessRecord

void appNotResponding(String activityShortComponentName,

ApplicationInfo aInfo,

…) {

if (isMonitorCpuUsage()) {

mService.updateCpuStatsNow();

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-29 16:26:00  更:2021-11-29 16:26:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:27:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码