【问题标题】:Listen and respond to ANR?聆听并回应 ANR?
【发布时间】:2012-02-05 12:57:26
【问题描述】:

有没有办法在您的应用触发 ANR(应用程序无响应)时获得通知?类似于默认异常处理程序?

期待“你会用它做什么”的答案,只是记录。不“做”任何事情。

【问题讨论】:

  • @WarrenFaith 伙计。你在说什么?我接受满意的答复。如果有人回复,但实际上并没有回答问题,我不接受他们。我的大部分问题真的很难,或者没有答案。通常到我问的时候,我已经看了很多,如果这是一个 Android 问题,而我自己找不到答案,那将是一个非常棘手的问题。我的 2K 代表来自回答问题。如果我的应用程序在市场上,我可以看到冻结。令人震惊。我想自己抓住它们。
  • @WarrenFaith PS。如果你能告诉我如何捕捉 ANR,我保证,你的回答将被接受。从您的“如果您的应用程序在市场上......”来看,您不知道如何,所以如果您这样回答,我不会“接受”它,因为它不是答案。正确的?还是因为你写的我就应该接受?
  • @WarrenFaith PPS,如果您的回答是“您不能那样做”,您需要引用带有链接的来源。否则只是猜测。
  • @WarrenFaith "Dude" 并不意味着所有权。所以,既然我不太了解你们的社区规则,我该怎么处理那些答案很糟糕的问题呢?我刚刚浏览了我的公开文件,发现有 2 个处于临界状态,所以接受了它们,即使他们有点打电话进来。其余的都有提交,但并没有真正“回答”任何事情。我不能完全“拒绝”他们。
  • @WarrenFaith 被冒犯了?不知道那是冒犯。那是我表达我的愤怒。就像,“伙计,让我休息一下”。我同意当我弄清楚时我应该填写自己的答案。当人们填写快速答案时,我通常不回复,因为他们显然只是想提高他们的分数。如果有合理的回答尝试,我想我一直在交流,至少最近是这样。新人的时候不懂规矩。无论如何,低于 50% 的可疑程度如何?我的大部分问题都没有很好的答案。期间。

标签: android


【解决方案1】:

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

  1. 尽快安排小代码在 UI 线程上运行。
  2. 等待 X 秒(由您决定)。
  3. 查看代码是否已运行:如果已运行,则返回 1
  4. 如果代码未运行,则表示 UI 线程已被阻塞至少 X 秒,引发 UI 线程堆栈跟踪异常

我已经写了a small library that does exactly that 并且我在 ACRA 中使用。

希望对你有帮助;)

【讨论】:

  • 我刚刚将这个库集成到我的应用程序中,它运行良好!非常感谢。
【解决方案2】:

没有。与您可以捕获的进程 VM 内发生的异常不同,ANR 是由 VM 外部的系统看门狗生成的。谷歌提供info on triggers and avoidance

【讨论】:

  • 我真的认为没有办法做到这一点,这非常令人沮丧。可以(也许)用我自己的 api 和线程做一些特别的事情来捕捉,但这似乎很 hacky。
【解决方案3】:

我一直在思考这个问题。您可以执行以下操作,尽管它相当笨拙。 ANR 将一个线程文件写入一个一般可读的目录:

/data/anr/traces.txt

您可以让服务在不同的进程中定期轮询该文件。如果日期发生变化,并且您的应用位于顶部,那么您可能遇到了 ANR 事件。

不过,我不能 100% 确定文件的格式。

【讨论】:

  • 这是我最喜欢的答案。得试试那个。不确定文件的格式是否重要:它将包含您的应用程序包的名称,因此您可以确保生成它的是您的应用程序。想知道文件系统观察者是否会处理该文件。然后在每次更改时,您都可以检查它是否包含您的包名称。也可以在应用启动时检查,以检查应用是否在 ANR 之后被用户杀死。
【解决方案4】:

这个小的ANR-WatchDog 线程可以帮助您监控应用程序的线程并在发生 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 的日志,请处理它。

    这里有一个导致 ANR 的应用的小示例:

    ...
    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 获得的日志:

    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
    

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

    【讨论】:

    • 对于 Jelly Bean 来说这是不可能的,因为您无法从其他进程或操作系统读取日志。此外,读取日志不是 Android SDK 的一部分。
    • correct.since 我没有 JB ,我看不出是否有任何解决方法。他们在 google IO 中说,即使现在它不起作用,也可以阅读您自己的应用程序的日志,所以我不知道这样的事情是否被认为是在应用程序内部(我想不是) .无论如何,这个解决方案从一开始就是一种解决方法。它应该适用于目前大约 99% 的设备。
    • 我有另一个想法。将在答案部分发布。
    猜你喜欢
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    • 1970-01-01
    相关资源
    最近更新 更多