一个简单的监测程序,可检测到鸿蒙系统的 ANR(Application Not Response-应用程序无响应)错误并引发有意义的异常
目前,ohos应用程序无法捕获和报告ANR错误。而调查ANR的唯一方法是提取文件/data/anr/traces.txt,不如选择我们自己的错误跟踪服务有效。
该组件设置了一个“watch dog”计时器,该计时器将检测UI线程何时停止响应。当监测到UI线程停止相应时,该组件会抛出一个具有堆栈轨迹的错误。
可以,由于这会引发错误,因此崩溃处理程序可以拦截该错误并按照所需的方式对其进行处理。
看门狗是一个简单的线程,它在循环中执行以下操作:
在 app/build.gradle
中, 添加:
compile project(path: ':anr_watchdog')
在 AbilityPackage类的 onCreate
中, 添加:
new ANRWatchDog().start();
该 ANRError
堆栈跟踪有点特殊, 它在你的应用程序运行的所有线程的堆栈跟踪。因此,在报告中, 每一个 caused by
部分都不是导致先例异常的原因, 而是不同线程的堆栈跟踪.
这是一个死锁示例:
鸿蒙手机的死锁示例:
2021-03-16 10:28:22.978 12535-12801/com.huawei.mytestapp E/AndroidRuntime: FATAL EXCEPTION: |ANR-WatchDog|
Process: com.huawei.mytestapp, PID: 12535
com.github.anrwatchdog.ANRError: Application Not Responding for at least 4000 ms.
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: main (state = BLOCKED)
at com.huawei.mytestapp.MainAbility.lock(MainAbility.java:83)
at com.huawei.mytestapp.MainAbility.access$500(MainAbility.java:15)
at com.huawei.mytestapp.MainAbility$8.onClick(MainAbility.java:170)
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: AppEyeUiProbeThread (state = RUNNABLE)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:363)
at android.os.Looper.loop(Looper.java:176)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerDaemon (state = WAITING)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:442)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:190)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:211)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:271)
从报告中,我们可以看到每一个线程的详细报告,根据Caused by 后面的堆栈追踪可以查看到死锁的原因
线程休眠报告:
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: AppEyeUiProbeThread (state = RUNNABLE)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:363)
at android.os.Looper.loop(Looper.java:176)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerDaemon (state = WAITING)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:442)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:190)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:211)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:271)
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: AppEyeUiProbeThread (state = RUNNABLE)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:363)
at android.os.Looper.loop(Looper.java:176)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerDaemon (state = WAITING)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:442)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:190)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:211)
无限循环报告:
2021-03-16 14:48:45.471 29817-30409/com.huawei.mytestapp E/AndroidRuntime: FATAL EXCEPTION: |ANR-WatchDog|
Process: com.huawei.mytestapp, PID: 29817
com.github.anrwatchdog.ANRError: Application Not Responding for at least 4000 ms.
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: main (state = RUNNABLE)
at com.huawei.mytestapp.MainAbility.InfiniteLoop(MainAbility.java:33)
at com.huawei.mytestapp.MainAbility.access$400(MainAbility.java:15)
at com.huawei.mytestapp.MainAbility$7.onClick(MainAbility.java:164)
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: AppEyeUiProbeThread (state = RUNNABLE)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:363)
at android.os.Looper.loop(Looper.java:176)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerDaemon (state = WAITING)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:442)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:190)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:211)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:271)
at java.lang.Daemons$Daemon.run(Daemons.java:137)
at java.lang.Thread.run(Thread.java:929)
Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerWatchdogDaemon (state = TIMED_WAITING)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:443)
at java.lang.Thread.sleep(Thread.java:359)
如何设置其他超时时间: ( 默认值为5000):
if (BuildConfig.DEBUG == false) {
new ANRWatchDog(10000 /*timeout*/).start();
}
默认情况下,如果在进行debug或应用程序正在等待debug,watch-dog将忽略ANR。这是因为它将执行暂停和断点检测为ANR。要禁用此功能并在debug的情况下抛出ANRError,可以添加setIgnoreDebugger(true)
:
new ANRWatchDog().setIgnoreDebugger(true).start();
如果您不想在检测到ANR时不使应用程序崩溃,则可以启用回调:
new ANRWatchDog().setANRListener(new ANRWatchDog.ANRListener() {
@Override
public void onAppNotResponding(ANRError error) {
// Handle the error. For example, log it to HockeyApp:
ExceptionHandler.saveException(error, new CrashManager());
}
}).start();
在生产环境中交付应用程序时,这一点非常重要。 当由最终用户掌握时,最好不要在5秒后崩溃,而只需将ANR报告给您使用的任何报告系统即可。也许,再过几秒钟后,该应用程序将“解冻”。
如果您希望仅在ANRError中报告自己的线程,而不是在所有线程(包括系统线程,例如该FinalizerDaemon
线程)中报告所有线程,则可以设置前缀:仅报告名称以该前缀开头的线程。
new ANRWatchDog().setReportThreadNamePrefix("APP:").start();
然后,在启动线程时,请不要忘记将其名称设置为以该前缀开头的名称(如果要报告该名称):
public class MyAmazingThread extends Thread {
@Override
public void run() {
setName("APP: Amazing!");
/* ... do amazing things ... */
}
}
如果只想拥有主线程堆栈跟踪而没有其他所有线程,则可以:
new ANRWatchDog().setReportMainThreadOnly().start();
有时,您想知道应用程序已经冻结了一段时间,但是还没有报告ANR错误。您可以定义在报告错误之前将被调用的拦截器。拦截器的作用是定义在给定的冻结持续时间下是否应提高或推迟ANR错误。
new ANRWatchDog(2000).setANRInterceptor(new ANRWatchDog.ANRInterceptor() {
@Override
public long intercept(long duration) {
long ret = 5000 - duration;
if (ret > 0) {
Log.w(TAG, "Intercepted ANR that is too short (" + duration + " ms), postponing for " + ret + " ms.");
}
return ret;
}
})
在此示例中,ANRWatchDog以2000毫秒的超时开始,但是拦截器将推迟错误,直到达到至少5000毫秒的冻结为止。
ANRWatchDog是一个线程,因此您可以随时中断它。
如果您正在使用Android的多进程功能进行编程(例如在新进程中启动活动),请记住,每个进程将需要ANRWatchDog线程。
原作者github地址:https://github.com/SalomonBrys/ANR-WatchDog#donate
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型