2012-01-08 27 views
10

当您的应用程序触发ANR(应用程序未响应)时,是否有办法通知?类似于默认的异常处理程序?收听并回复ANR?

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

+3

@WarrenFaith Dude。你在说什么?我接受满意的答案。如果有人回复,但实际上并没有回答这个问题,我不接受他们。我的大部分问题都非常难*,或者没有答案。通常在我问的时候,我看了很多,如果它是一个Android问题,而且我自己也找不到答案,那么它将成为一个非常棘手的问题。我的2K代表是回答问题。如果我的应用程序在市场上,我可以看到冻结。令人震惊的。我想亲自看看。 – 2012-01-08 20:42:51

+1

@WarrenFaith PS。如果你能告诉我如何抓住ANR,我保证,你的答案将被接受。从你的“如果你的应用程序在市场上......”“,你不知道如何,所以如果你回答这个问题,我不会”接受“它,因为它不是答案。对吗?或者我应该接受它,只是因为你写了它? – 2012-01-08 20:44:19

+2

@WarrenFaith PPS ,如果你的答案是“你不能这样做”,你需要引用一个链接来源,否则它只是一个猜测。 – 2012-01-08 20:45:13

回答

1

不。不像你的进程虚拟机中发生的异常可以捕获,ANR由系统监视器在虚拟机之外生成。 Google提供info on triggers and avoidance

+0

我真的觉得没有办法做到这一点,这非常令人沮丧。可以(也许)用我自己的api和线程来做一些特殊的事情,但这看起来很诡异。 – 2012-02-17 00:10:21

0

您可以使用监听日志(使用线程)的服务(最好是前台服务),并且如果有指示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(); 
     } 
     } 
    }); 
... 

下面是我从logcat中得到了时,我得到了ANR日志:

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 

所以,是的,我想这是可能的。

+0

由于您无法从其他进程或操作系统读取日志,因此无法使用Jelly Bean。此外,阅读日志不是Android SDK的一部分。 – CommonsWare 2012-08-03 13:27:02

+0

correct.since我没有JB,我无法看到是否有任何解决方法。他们在google IO中表示,即使现在它不能工作,也可以阅读你自己的应用程序的日志,所以我不知道这样的事情是否被认为是在应用程序内部(我猜这不是)无论如何,这个解决方案从一开始就是一种解决方法。它应该适用于目前约99%的设备。 – 2012-08-03 14:00:44

+0

我有另一个想法。将在答案部分发布。 – 2012-08-04 16:21:20

5

我一直在想这个问题。你可以做到以下,虽然它相当重的手。 ANR的写了一个线程文件到一般可读目录:

/data/anr/traces.txt

你可以有一个服务,在不同的进程,调查周期性文件。如果日期发生变化,并且您的应用位于顶部,那么您可能有ANR事件。

虽然我并不是100%确定文件的格式。

+0

这是我最喜欢的答案。必须尝试。不确定文件的格式很重要:它将包含您的应用程序包的名称,因此您可以确保它是生成它的应用程序。想知道如果文件系统观察员可以在该文件上工作。然后在每一个变化你可以检查它是否包含你的包名称。也可以在应用程序启动时检查,以检查应用程序是否被用户杀死了ANR。 – 3c71 2012-12-19 16:00:35

3

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

  1. 附表小码将尽快在UI线程上运行。
  2. 等待X秒(您决定)。
  3. 查看代码是否已经运行:如果已经运行,返回1
  4. 如果代码没有运行,则意味着UI线程已被阻塞至少X秒,并通过UI线程引发异常堆栈跟踪

我写了a small library that does exactly that,我用ACRA。

我希望它有帮助;)