关于android:听取并回应ANR?

Listen and respond to ANR?

当你的应用程序触发一个ANR(应用程序没有响应)时,有没有办法得到通知?类似于默认的异常处理程序?

期待着"你会用它做什么"的答案,只需记录。什么都不做。


我已经想了很久了。你可以做以下的事情,尽管这很重。ANR将线程文件写入一个一般可读的目录:

/数据/anr/traces.txt

您可以有一个服务,在不同的过程中,定期轮询该文件。如果日期改变了,你的应用程序在最上面,那么你可能有一个ANR事件。

不过,我不完全确定文件的格式。


由于系统看门狗不警告应用程序,因此应用程序本身可以拥有自己的看门狗。步骤很简单,只需启动一个循环执行以下操作的线程:

  • 安排小代码尽快在UI线程上运行。
  • 等待X秒(由您决定)。
  • 查看代码是否已运行:如果已运行,请返回1
  • 如果代码没有运行,这意味着UI线程已被阻塞至少X秒,并引发一个带有UI线程堆栈跟踪的异常
  • 我已经写了一个小的图书馆,可以做到这一点,并且我和ACRA一起使用。

    希望能有所帮助;)


    不。与您可以捕获的进程虚拟机中发生的异常不同,ANR是由系统看门狗生成的,在您的虚拟机之外。谷歌提供关于触发和回避的信息


    这个小的ANR看门狗线程可以帮助您监控应用程序的线程,并在发生ANR时得到通知。

    1
    2
    3
    4
    5
    6
    7
    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();

    您可以使用一个服务(最好是前台服务)来监听日志(使用线程),如果有一个日志指示ANR,请处理它。

    下面是一个小的应用程序示例,它会导致ANR:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ...
    findViewById(R.id.button).setOnClickListener(new OnClickListener()
      {
        @Override
        public void onClick(final View v)
          {
          try
            {
            Thread.sleep(10000);
            }
          catch(final InterruptedException e)
            {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }
          }
      });
    ...

    这是我得到ANR时从logcat那里得到的日志:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    08-03 13:02:37.746: E/ActivityManager(158): ANR in com.example.anr (com.example.anr/.MainActivity)
    08-03 13:02:37.746: E/ActivityManager(158): Reason: keyDispatchingTimedOut
    08-03 13:02:37.746: E/ActivityManager(158): Load: 6.19 / 2.37 / 0.86
    08-03 13:02:37.746: E/ActivityManager(158): CPU usage from 5598ms to 0ms ago:
    08-03 13:02:37.746: E/ActivityManager(158):   2.6% 158/system_server: 2.5% user + 0.1% kernel / faults: 86 minor
    08-03 13:02:37.746: E/ActivityManager(158):   0.5% 298/com.android.phone: 0.3% user + 0.1% kernel / faults: 15 minor
    08-03 13:02:37.746: E/ActivityManager(158):   0% 35/rild: 0% user + 0% kernel
    08-03 13:02:37.746: E/ActivityManager(158): 4.6% TOTAL: 3.9% user + 0.6% kernel
    08-03 13:02:37.746: E/ActivityManager(158): CPU usage from 2029ms to 2654ms later:
    08-03 13:02:37.746: E/ActivityManager(158):   11% 158/system_server: 4.8% user + 6.4% kernel / faults: 2 minor
    08-03 13:02:37.746: E/ActivityManager(158):     11% 192/InputDispatcher: 4.8% user + 6.4% kernel
    08-03 13:02:37.746: E/ActivityManager(158):     1.6% 163/Compiler: 1.6% user + 0% kernel
    08-03 13:02:37.746: E/ActivityManager(158):     1.6% 193/InputReader: 0% user + 1.6% kernel
    08-03 13:02:37.746: E/ActivityManager(158): 18% TOTAL: 9.3% user + 9.3% kernel

    所以,是的,我认为这是可能的。