Giter Club home page Giter Club logo

anr-watchdog's Introduction

Maven Central MIT License GitHub issues Donate

ANR-WatchDog

A simple watchdog that detects Android ANRs (Application Not Responding).

Table of contents

Why it exists

There is currently no way for an android application to catch and report ANR errors.
If your application is not in the play store (either because you are still developing it or because you are distributing it differently), the only way to investigate an ANR is to pull the file /data/anr/traces.txt.
Additionally, we found that using the Play Store was not as effective as being able to choose our own bug tracking service.

There is an issue entry in the android bug tracker describing this lack, feel free to star it ;)

What it does

It sets up a "watchdog" timer that will detect when the UI thread stops responding. When it does, it raises an error with all threads stack traces (main first).

Can it work with crash reporters?

Yes! I'm glad you asked: That's the reason why it was developed in the first place!
As this throws an error, a crash handler can intercept it and handle it the way it needs.

Known working crash reporters include:

And there is no reason why it should not work with [insert your favourite crash reporting system here].

How it works

The watchdog is a simple thread that does the following in a loop:

  1. Schedules a runnable to be run on the UI thread as soon as possible.
  2. Wait for 5 seconds. (5 seconds is the default, but it can be configured).
  3. See if the runnable has been run. If it has, go back to 1.
  4. If the runnable has not been run, which means that the UI thread has been blocked for at least 5 seconds, it raises an error with all running threads stack traces.

Usage

Install

With Gradle / Android Studio

  1. In the app/build.gradle file, add:

    implementation 'com.github.anrwatchdog:anrwatchdog:1.4.0'
    
  2. In your application class, in onCreate, add:

    new ANRWatchDog().start();

With Eclipse

  1. Download the latest jar

  2. Put the jar in the libs/ directory of your project

Reading the ANRError exception report

The ANRError stack trace is a bit particular, it has the stack traces of all the threads running in your application. So, in the report, each caused by section is not the cause of the precedent exception, but the stack trace of a different thread.

Here is a dead lock example:

FATAL EXCEPTION: |ANR-WatchDog|
    Process: anrwatchdog.github.com.testapp, PID: 26737
    com.github.anrwatchdog.ANRError: Application Not Responding
    Caused by: com.github.anrwatchdog.ANRError$_$_Thread: main (state = WAITING)
        at testapp.MainActivity$1.run(MainActivity.java:46)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
    Caused by: com.github.anrwatchdog.ANRError$_$_Thread: APP: Locker (state = TIMED_WAITING)
        at java.lang.Thread.sleep(Native Method)
        at java.lang.Thread.sleep(Thread.java:1031)
        at java.lang.Thread.sleep(Thread.java:985)
        at testapp.MainActivity.SleepAMinute(MainActivity.java:18)
        at testapp.MainActivity.access$100(MainActivity.java:12)
        at testapp.MainActivity$LockerThread.run(MainActivity.java:36)

From this report, we can see that the stack traces of two threads. The first (the "main" thread) is stuck at MainActivity.java:46 while the second thread (named "App: Locker") is locked in a Sleep at MainActivity.java:18.
From there, if we looked at those two lines, we would surely understand the cause of the dead lock!

Note that some crash reporting library (such as Crashlytics) report all thread stack traces at the time of an uncaught exception. In that case, having all threads in the same exception can be cumbersome. In such cases, simply use setReportMainThreadOnly().

Configuration

Timeout (minimum hanging time for an ANR)

To set a different timeout (5000 millis is the default):

if (BuildConfig.DEBUG == false) {
  new ANRWatchDog(10000 /*timeout*/).start();
}

Debugger

By default, the watchdog will ignore ANRs if the debugger is attached or if the app is waiting for the debugger to attach. This is because it detects execution pauses and breakpoints as ANRs. To disable this and throw an ANRError even if the debugger is connected, you can add setIgnoreDebugger(true):

new ANRWatchDog().setIgnoreDebugger(true).start();

On ANR callback

If you would prefer not to crash the application when an ANR is detected, you can enable a callback instead:

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();

This is very important when delivering your app in production. When in the hand of the final user, it's probably better not to crash after 5 seconds, but simply report the ANR to whatever reporting system you use. Maybe, after some more seconds, the app will "de-freeze".

Filtering reports

If you would like to have only your own threads to be reported in the ANRError, and not all threads (including system threads such as the FinalizerDaemon thread), you can set a prefix: only the threads whose name starts with this prefix will be reported.

new ANRWatchDog().setReportThreadNamePrefix("APP:").start();

Then, when you start a thread, don't forget to set its name to something that starts with this prefix (if you want it to be reported):

public class MyAmazingThread extends Thread {
    @Override
    public void run() {
        setName("APP: Amazing!");
        /* ... do amazing things ... */
    }
}

If you want to have only the main thread stack trace and not all the other threads, you can:

new ANRWatchDog().setReportMainThreadOnly().start();

ANR Interceptor

Sometimes, you want to know that the application has froze for a certain duration, but not report the ANR error just yet. You can define an interceptor that will be called before reporting an error. The role of the interceptor is to define whether or not, given the given freeze duration, an ANR error should be raised or postponed.

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;
    }
})

In this example, the ANRWatchDog starts with a timeout of 2000 ms, but the interceptor will postpone the error until at least 5000 ms of freeze has been reached.

Watchdog thread

ANRWatchDog is a thread, so you can interrupt it at any time.

If you are programming with Android's multi process capability (like starting an activity in a new process), remember that you will need an ANRWatchDog thread per process.

Donate

ANR-Watchdog is free to use for both non-profit and commercial use and always will be.

If you wish to show some support or appreciation to my work, you are free to donate!

This would be (of course) greatly appreciated but is by no means necessary to receive help or support, which I'll be happy to provide for free :)

anr-watchdog's People

Contributors

ashishkrishnan avatar fractalwrench avatar jqrgen avatar juliengenoud avatar libtastic avatar ozmium avatar salomonbrys avatar shashachu avatar sjp4 avatar wasd845 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

anr-watchdog's Issues

Main thread is in runnable state but still ANR is detected.

Hello,
We integrated your library and we are seeing some weird logs on our crashlytics, like below:

Caused by com.github.anrwatchdog.ANRError$$$_Thread
main (state = RUNNABLE)

The state is runnable but it still shows up as an ANR. Is this a false positive?

I too was having this issue earlier, it seems when you Log a non-runtime exception in crashlytics it creates nonfatal exceptions in fabric dashboard since ANRs don't necessarily crash an application. You need to toggle the switch in the fabric dashboard to show all exceptions including non-fatals as by default it only shows fatal exceptions.

I too was having this issue earlier, it seems when you Log a non-runtime exception in crashlytics it creates nonfatal exceptions in fabric dashboard since ANRs don't necessarily crash an application. You need to toggle the switch in the fabric dashboard to show all exceptions including non-fatals as by default it only shows fatal exceptions.

screen shot 2017-09-27 at 11 53 25 pm

Another issue might be proguard which when enabled strips some important classes required by anrWatchDog. To prevent that use the following rule in your proguard-rules.pro file.

-keep class com.github.anrwatchdog.** { *; }

You might also want to do the following to change the error into string

  anrWatchDog.setANRListener(new ANRWatchDog.ANRListener() {
            @Override
            public void onAppNotResponding(ANRError error) {
                StringWriter sw = new StringWriter();
                error.printStackTrace(new PrintWriter(sw));
                CrashUtil.logException(new RuntimeException(sw.toString()));
            }
        });

Hope it helps!

Originally posted by @navaneet in #29 (comment)

Precompiled test app

It would be nice if you could provide the test app as pre-compiled apk, i need it to test some tasker stuff ^~^


Sent from my Lenovo TAB 2 A10-70L running Android 6.0 via OctoDroid v.4.2.0

It's possible to make it work in debug mode too

Re note:

Note that this will not enable the watchdog in debug mode, because the watchdog will prevent the debugger from hanging execution at breakpoints or exceptions (it will detect the debugging pause as an ANR).

You could easily work around this by checking android.os.Debug#isDebuggerConnected whenever you detect an ANR and just ignore it.

Can you think of any reason not to do this by default?

Not really issues -- more like a couple questions

Android typically traps ANRs (at least for touch events) after 500ms. By having our ANR timeout higher than that is it possible we could ANR, present a wait/close message, answer close, before the watchdog's ANR event fires?

My thought is yes. Do you see any ramifications about running with a 500 ms timeout in production? I'm only talking about the main thread monitor. I do my own sleeps in other threads that would definitely trip it if I were monitoring them too.

The next comment is really more an annoyance with Google. I absolutely hate not being able to interrupt and join ANRWatchDog onTerminate() because for whatever reason Google refuses to give us a means of (easily / logically) determining when an application closes.

I have the following in my onTerminate() but I know it will never be called. I'm guessing this why you simply just create an anonymous instance in all your examples, correct?

    anrWatchDog.interrupt();

    try {
        anrWatchDog.join();
    } catch (InterruptedException e) {
        Crashlytics.logException(e);
    }

ExceptionHandler is missing

ExceptionHandler.saveException(error, new CrashManager());

Im currently using Crashlytics. How do I save exceptions using your code?

if (_namePrefix != null) should be if (!TextUtils.isEmpty(_namePrefix))

if (_namePrefix != null) should be if (!TextUtils.isEmpty(_namePrefix)) .
Because if I ignore setting the only main Thread, error = ANRError.New(_namePrefix, _logThreadsWithoutStackTrace) will be executed, but it is not efficient.

           // If the main thread has not handled _ticker, it is blocked. ANR. 
            if (_tick == lastTick) {
                ANRError error;
                if (_namePrefix != null)
                    error = ANRError.New(_namePrefix, _logThreadsWithoutStackTrace);
                else 
                    error = ANRError.NewMainOnly();
                _anrListener.onAppNotResponding(error);
                return ; 
            } 

rooted

my phone is rooted and i have no control wha to do

It seems not so good to start the anr-watchdog on application oncreate

If using new ANRWatchDog().start() on application oncreate function. then it will begin to post a delay message(defalut 5000ms), while on application oncreate function, there may be init some tasks in UI Thread may need more than 5000 ms with some low mobile devices, thus it will cause the not real anr with anr-watchDog.

Support for getStackTrace() and setStackTrace()

Hi Salomon,

We're in the process of integrating your plugin in our app.

It would be very beneficial to be able to manipulate the stack trace before sending the ANRError to Firebase Crashlytics, so we can group the ANR issues together in the console there. Crashlytics groups the issues based on the topmost frame in the stack trace, so we were thinking of adding a custom frame to the top to let Firebase know that it belongs next to other ANR issues.

I've tried using couple of methods inherited from Throwable, but they don't seem to be overriden in the ANRError class - getStackTrace() returns an empty array and setStackTrace() doesn't seem to do anything.

So my questions are:

  1. Is there a way to add a custom frame to the top of the stack trace in the ANRError?
  2. If not, do you plan to add the support for manipulating the stack trace of the ANRError?

BTW, thanks for creating this plugin and making it open-source! It's a lifesaver amidst the current shortage of ANR detectors 😃

Race condition for _tick and _reported

  1. Let assume that we use all the default callbacks and values.
  2. When the _ticker is not called during 5sec and we recognise this as ANR and send the report, assign interval initial value and set the _reported to true.
  3. We start our while cycle from the beginning: _tick is not 0 so we don't schedule _ticker again - it is ok, next we put our thread to the sleep on 5sec one more time.
  4. But imagine that our _ticker is not called again during this 5s but is called at the time when we step on condition "if (_tick != 0 && !_reported)" and it is race condition because we write and read _tick and _reported at the same moment of time.

Best,
Taras

I am getting anr exception, don't know what is root cause

01-25 15:37:59.706 17949-17956/in.codersbyte.namostu I/art: Thread[3,tid=17956,WaitingInMainSignalCatcherLoop,Thread*=0x7fa064f400,peer=0x12c24a60,"Signal Catcher"]: reacting to signal 3
01-25 15:37:59.901 17949-17956/in.codersbyte.namostu I/art: Wrote stack traces to '/data/anr/traces.txt'
01-25 15:37:59.949 17949-18055/in.codersbyte.namostu E/AndroidRuntime: FATAL EXCEPTION: |ANR-WatchDog|
                                                                       Process: in.codersbyte.namostu, PID: 17949
                                                                       com.github.anrwatchdog.ANRError: Application Not Responding
                                                                       Caused by: com.github.anrwatchdog.ANRError$$$_Thread: main (state = RUNNABLE)
                                                                           at android.view.ThreadedRenderer.nSetStopped(Native Method)
                                                                           at android.view.ThreadedRenderer.setStopped(ThreadedRenderer.java:494)
                                                                           at android.view.ViewRootImpl.draw(ViewRootImpl.java:2831)
                                                                           at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2646)
                                                                           at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2253)
                                                                           at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1288)
                                                                           at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6359)
                                                                           at android.view.Choreographer$CallbackRecord.run(Choreographer.java:873)
                                                                           at android.view.Choreographer.doCallbacks(Choreographer.java:685)
                                                                           at android.view.Choreographer.doFrame(Choreographer.java:621)
                                                                           at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:859)
                                                                           at android.os.Handler.handleCallback(Handler.java:754)
                                                                           at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                           at android.os.Looper.loop(Looper.java:163)
                                                                           at android.app.ActivityThread.main(ActivityThread.java:6237)
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:877)
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: Answers Events Handler1 (state = TIMED_WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160)
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325)
                                                                           at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:201)
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2077)
                                                                           at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1103)
                                                                           at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1084)
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058)
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                           at io.fabric.sdk.android.services.common.ExecutorUtils$1$1.onRun(ExecutorUtils.java:75)
                                                                           at io.fabric.sdk.android.services.common.BackgroundPriorityRunnable.run(BackgroundPriorityRunnable.java:30)
                                                                           at java.lang.Thread.run(Thread.java:760)
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: AsyncTask #10 (state = TIMED_WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160)
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325)
                                                                           at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:201)
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2077)
                                                                           at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:438)
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1057)
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: AsyncTask #9 (state = TIMED_WAITING)
                                                                           at java.lang.Object.wait(Native Method) 
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160) 
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325) 
                                                                           at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:201) 
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2077) 
                                                                           at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:438) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1057) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118) 
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: Crashlytics Exception Handler1 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160)
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325)
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035)
                                                                           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058)
01-25 15:37:59.950 17949-18055/in.codersbyte.namostu E/AndroidRuntime:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                           at io.fabric.sdk.android.services.common.ExecutorUtils$1$1.onRun(ExecutorUtils.java:75)
                                                                           at io.fabric.sdk.android.services.common.BackgroundPriorityRunnable.run(BackgroundPriorityRunnable.java:30)
                                                                           	... 1 more
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FileObserver (state = RUNNABLE)
                                                                           at android.os.FileObserver$ObserverThread.observe(Native Method)
                                                                           at android.os.FileObserver$ObserverThread.run(FileObserver.java:85)
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerDaemon (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Object.wait(Object.java:407)
                                                                           at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:188)
                                                                           at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:209)
                                                                           at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:204)
                                                                           at java.lang.Thread.run(Thread.java:760)
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerWatchdogDaemon (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Daemons$FinalizerWatchdogDaemon.sleepUntilNeeded(Daemons.java:269)
                                                                           at java.lang.Daemons$FinalizerWatchdogDaemon.run(Daemons.java:249)
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FrescoDecodeExecutor-1 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160)
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325)
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035)
                                                                           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058)
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                           at com.facebook.imagepipeline.core.PriorityThreadFactory$1.run(PriorityThreadFactory.java:53)
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FrescoIoBoundExecutor-1 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method) 
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160) 
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325) 
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161) 
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035) 
                                                                           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118) 
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                                                                           at com.facebook.imagepipeline.core.PriorityThreadFactory$1.run(PriorityThreadFactory.java:53) 
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FrescoLightWeightBackgroundExecutor-1 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method) 
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160) 
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325) 
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161) 
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035) 
                                                                           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118) 
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                                                                           at com.facebook.imagepipeline.core.PriorityThreadFactory$1.run(PriorityThreadFactory.java:53) 
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: HeapTaskDaemon (state = BLOCKED)
                                                                           at dalvik.system.VMRuntime.runHeapTasks(Native Method)
                                                                           at java.lang.Daemons$HeapTaskDaemon.run(Daemons.java:433)
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: OkHttp ConnectionPool (state = TIMED_WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at com.android.okhttp.ConnectionPool.performCleanup(ConnectionPool.java:307)
                                                                           at com.android.okhttp.ConnectionPool.runCleanupUntilPoolIsEmpty(ConnectionPool.java:244)
                                                                           at com.android.okhttp.ConnectionPool.-wrap0(ConnectionPool.java)
                                                                           at com.android.okhttp.ConnectionPool$1.run(ConnectionPool.java:98)
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: Okio Watchdog (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at com.android.okhttp.okio.AsyncTimeout.awaitTimeout(AsyncTimeout.java:311)
                                                                           at com.android.okhttp.okio.AsyncTimeout.-wrap0(AsyncTimeout.java)
                                                                           at com.android.okhttp.okio.AsyncTimeout$Watchdog.run(AsyncTimeout.java:286)
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: Queue (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160)
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325)
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035)
01-25 15:37:59.951 17949-18055/in.codersbyte.namostu E/AndroidRuntime:     at java.util.concurrent.PriorityBlockingQueue.take(PriorityBlockingQueue.java:519)
                                                                           at io.fabric.sdk.android.services.concurrency.DependencyPriorityBlockingQueue.performOperation(DependencyPriorityBlockingQueue.java:197)
                                                                           at io.fabric.sdk.android.services.concurrency.DependencyPriorityBlockingQueue.get(DependencyPriorityBlockingQueue.java:236)
                                                                           at io.fabric.sdk.android.services.concurrency.DependencyPriorityBlockingQueue.take(DependencyPriorityBlockingQueue.java:65)
                                                                           at io.fabric.sdk.android.services.concurrency.DependencyPriorityBlockingQueue.take(DependencyPriorityBlockingQueue.java:46)
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058)
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                           at java.lang.Thread.run(Thread.java:760)
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: ReferenceQueueDaemon (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Daemons$ReferenceQueueDaemon.run(Daemons.java:150)
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: Thread-18 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160)
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325)
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035)
                                                                           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058)
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: Thread-19 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method) 
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160) 
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325) 
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161) 
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035) 
                                                                           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118) 
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: Thread-7 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method) 
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160) 
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325) 
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161) 
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035) 
                                                                           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118) 
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: fifo-pool-thread-0 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160)
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325)
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035)
                                                                           at java.util.concurrent.PriorityBlockingQueue.take(PriorityBlockingQueue.java:519)
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058)
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                           at java.lang.Thread.run(Thread.java:760)
                                                                           at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: pool-1-thread-1 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method)
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160)
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325)
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035)
                                                                           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058)
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                           at java.lang.Thread.run(Thread.java:760)
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: pool-7-thread-1 (state = WAITING)
                                                                           at java.lang.Object.wait(Native Method) 
                                                                           at java.lang.Thread.parkFor$(Thread.java:2160) 
                                                                           at sun.misc.Unsafe.park(Unsafe.java:325) 
                                                                           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161) 
                                                                           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035) 
                                                                           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058) 
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118) 
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                                                                           at java.lang.Thread.run(Thread.java:760) 
                                                                        Caused by: com.github.anrwatchdog.ANRError$$$_Thread: |ANR-WatchDog| (state = RUNNABLE)
                                                                           at dalvik.system.VMStack.getThreadStackTrace(Native Method)
01-25 15:37:59.952 17949-18055/in.codersbyte.namostu E/AndroidRuntime:     at java.lang.Thread.getStackTrace(Thread.java:1565)
                                                                           at java.lang.Thread.getAllStackTraces(Thread.java:1615)
                                                                           at com.github.anrwatchdog.ANRError.New(ANRError.java:72)
                                                                           at com.github.anrwatchdog.ANRWatchDog.run(ANRWatchDog.java:209)

Anr is not being detected sometimes

I have an app, I made the app to cause the ANR by following code on tap of a button:

int i = 0;
while(true){
    i++; // this will cause anr
}

The above code causes the ANR, app also shows the anr dialog (basically, app not responding, wait or close the app), but the problem is ANRWatchDog isn't able to detect the anr sometimes, sometimes it does.

Please have a look at the above issue reported and let me know.

Thanks!

Pinterest

<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-53W2RTH');</script>

onAppNotResponding not working properly

Hi ,

As mentioned in doc about onAppNotResponding call back.
It is said final user will not get app not responding dialog if we override this function.

But I used below code :-
new ANRWatchDog().setReportMainThreadOnly().start();
new ANRWatchDog().setANRListener(new ANRWatchDog.ANRListener() {
@OverRide
public void onAppNotResponding(ANRError error) {
if (!isDebuggerConnected()) {
throw error;
}
}
}).start();

And I am getting App Not responding dialog.

Kindly help me.

iMac

how to put and iMac in safe mode with command prompt when it wont go pass recovery mode how can i get back to desktop

Debug.waitForDebugger() conflict

When I place Debug.waitForDebugger(); into some method there's always ANR. setIgnoreDebugger() is not set.

Expected: watchdog does not throw on Debug waits.

Few queries - Not exactly issue

I am using both ANR-Watchdog and Dropbox to catch app's anr.
I am seeing below given cases:

  1. When ANR-Watchdog is reporting the ANR at that time Dropbox is not having ANR entry.
  2. When ever ANR-Watchdog misses to throw the exception, at that time we are having Dropbox entry.
  3. very rarely we are seeing both Watchdog and Dropbox having same entries.

Could you please advice, which one of above should actually happen as per your experience?
Though i am seeing that ANRWatchdog is efficient than Dropbox. But because of watchdog missing few anr i had to introduce dropbox mechanism.

ANR-WatchDog not works with Bugsnag

I'm not sure if the problem is with WatchDog or Bugsnag. We implemented WatchDog in our project but we have some problems with ANR errors - they aren't sent to Bugsnag, but with Fabric everything works correctly.

new ANRWatchDog().setANRListener(new ANRWatchDog.ANRListener() {
    @Override
    public void onAppNotResponding(final ANRError error) {
        Bugsnag.notify(error);
        throw error;
    }
}).start();

Cannot download version 1.4.0

I added com.github.anrwatchdaog:anrwatchdog:1.4.0 but still cant find ANRWatchDog and ANRError
I tried it in the test app

dependencies {
    // implementation project(':anr-watchdog')
    implementation 'com.github.anrwatchdaog:anrwatchdog:1.4.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
}

Screenshot 2021-03-01 at 1 42 22 PM

sometimes it will not cash when I use the watchdog

I use the watchdog in my app, why sometime it will crash when anr, but sometimes the android os anr dialog will appear(then it will not crash)?
I just code it by the default way: new ANRWatchDog().start();

Watchdog send error to Fabric (Crashlytics)

Hello,
I implemented WathchDog in my project. Boot seem like it has problem with WatchDog version 1.0.3.
The logs were not send to Fabric although I catched the error . Please help me check it.
Here's the code
new ANRWatchDog().setANRListener(new ANRWatchDog.ANRListener() {
@OverRide
public void onAppNotResponding(ANRError arg0) {
Crashlytics.getInstance().core.logException(arg0);
}
}).start();

Thank you.

watch for other applications being anred

Hi. Is there any way to watch for other apps anr??? I mean for example I write an app called anrwatcher and it reports all the anrs from the all apps run through device. Thanks in advance.

Real ANR timeout

I tested your library and I found that reaction on ANR is much bigger than the value set in constructor by new ANRWatchDog(10000 /*timeout*/).start();

I found that it is caused by this code

        try {
            Thread.sleep(interval);
        } catch (InterruptedException e) {
            _interruptionListener.onInterrupted(e);
            return ;
        }

If there is no ANR, your thread basically sleeps for 10000 ms in this case.
During this 10s can happen that thread is blocked, for example in the middle.
So it is already 5s blocked at the end, but tick has arrived before it happens.
So it will sleep again 10s, and then it detects ANR after 15s.
So theoretically it can be almost double of configured time.

The only workaround is to use low timeout interval, for example, 500ms
And then use ANRInterceptor and detect real 10s here.

But this behavior is not clear from the documentation.

Thread timeout?

Hey, this is a fantastic project and very useful indeed. I am using the below code for checking ANRs :

` // ANR Reporting

    /*if (BuildConfig.DEBUG == false) {
        new ANRWatchDog(5000 *//*timeout*//*).start();
    }*/

    new ANRWatchDog().setIgnoreDebugger(true).start();

    // Prevent app termination
    new ANRWatchDog().setANRListener(new ANRWatchDog.ANRListener() {
        @Override
        public void onAppNotResponding(ANRError error) {
            // Handle the error. For example, log it to HockeyApp:
            Intent cu = new Intent(UriActivity.this, CrashActivity.class);
            if(error!=null) {
                cu.putExtra("errorx", error.toString());
            }
            startActivity(cu);
        }
    }).start();

    // ANR Reporting End`

My questions are

  1. Do I need to insert above code for every activity to check ANRs or launcher activity itself is enough? Meaning, does it have context only for the current activity or has context of all activities in the app.
    Lets say I launch another activity other than the launcher activity using a service, then will I get ANR on that particular non launcher activity? There can be a limit to number of parallel threads allowed on a particular android device that is why I wanted raise this question. Say I use above code in 5 activities, I will have 4 unnecessary parallel threads.

  2. Can I use it on any of my apps with commercial use? Is the license Open Source?

Thanks!

anr debug exception please help me

com.github.anrwatchdog.ANRError: Application Not Responding
Caused by: com.github.anrwatchdog.ANRError$$_Thread: main (state = RUNNABLE)
at com.android.org.conscrypt.NativeCrypto.RSA_generate_key_ex(Native Method)
at com.android.org.conscrypt.OpenSSLRSAKeyPairGenerator.generateKeyPair(OpenSSLRSAKeyPairGenerator.java:44)
at java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:276)
at com.mcnc.parecis.xxx.xxx.net.RSA.java.lang.String getRSAKeySet()(SourceFile:3)
at com.mcnc.parecis.xxx.xxx.App.void onCreate()(SourceFile:20)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1036)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6317)
at android.app.ActivityThread.access$1800(ActivityThread.java:221)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1860)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7225)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

please help me why this anr exception occur as it is very hard to debug anr exception
please help me how to solve this.

How to be sure if main thread is blocked or not?

Hi, I've found your project with how to detect ANR in Android and I found it very useful, thanks a lot. But there is a port that I don't quite understand that how do you be sure if main thread is blocked?
Your code:

public void run() {
    setName("|ANR-WatchDog|");

    int lastTick;
    while (!isInterrupted()) {
        lastTick = _tick;
        _uiHandler.post(_ticker);
        try {
            Thread.sleep(_timeoutInterval);
        }
        catch (InterruptedException e) {
            _interruptionListener.onInterrupted(e);
            return ;
        }

        // If the main thread has not handled _ticker, it is blocked. ANR.
        if (_tick == lastTick) {
            ANRError error;
            if (_namePrefix != null)
                error = ANRError.New(_namePrefix, _logThreadsWithoutStackTrace);
            else
                error = ANRError.NewMainOnly();
            _anrListener.onAppNotResponding(error);
            return ;
        }
    }
}

The value of current _tick is passed to lastTick before Runnable _ticker is passed to main thread. Let's assume _tick is 0 which means lastTick is 0 as well. Then the watchDog thread is gonna sleep for 5s without interruption. Then the code check if the new _tick equals lastTick:

if (_tick == lastTick)

By that I saw that if the new value of _tick equals the value of lastTick then we know the thread is blocked. This is the part I just don't understand, isn't it possible that the new value of _tick is 0 since its value will be set between 0~9 (_tick = (_tick + 1) % 10)??? Is there anything wrong about my analysis about this? I knew that it has to be something wrong with myself but I just can't find out, hope somebody can help me, thanks a lot!

Suspiciously short list of threads when recording ANRError as Crashlytics non-fatal exception

Hi!

I integrated ANR-WatchDog to a Unity game using custom implementation of UnityPlayerActivity.

At first I released a game with the default behaviour of the ANR-WatchDog.
My app crashed due to unhandled ANRError and Firebase Crashlytics recorded something around 40 threads at this moment including UnityMain thread and others. I used setReportMainThreadOnly() because Crashlytics collects all threads by itself on fatal errors.

Then I turned this crash to a non-fatal using this code:

    @Override protected void onCreate(Bundle savedInstanceState)
    {
        ANRWatchDog watchDog = new ANRWatchDog();
        watchDog.setANRListener(new ANRWatchDog.ANRListener() {
            @Override
            public void onAppNotResponding(ANRError error) {
                FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
                crashlytics.recordException(error);
            }
        });
        watchDog.start();

        super.onCreate(savedInstanceState);
    }

This code records ANRError as a non-fatal exception and Crashlytics attaches stack traces contained in ANRError. That is why you do not see setReportMainThreadOnly() here any more. But now crash reports a very short, containing only 8-10 threads. What is strange there were no UnityMain thread while this non-fatal was triggered in the middle of a gameplay.

Please help, any ideas on how to get full list of stack traces attached?

Indirect Dependency on API Level 15

When I include ANR-WatchDog using gradle, I get the following error when I sync the Android Studio project:

Error:Execution failed for task ':app:prepareDebugDependencies'.
ERROR: Debug has an indirect dependency on Android API level 15, but minSdkVersion for variant 'debug' is API level 10

Is there any reason why API Levels lower than 15 aren't supported?

看了下你的源码,原理比较简单,但是还是有不准确的情况

看了下你的源码,原理比较简单,但是还是有不准确的情况,因为你靠的就是UiHandler来实现你的目标代码是否响应了,来判断当前UI是否卡顿,表面上看是可信,只是粗略上的数据。实际上,这样做不仅多起了一个线程去Dispatch 一个消息,性能消耗了,而且不能准确的判断到底是那个函数耗时了(通过消息队列来判断,实际上有时间差,不够精准)!
我觉得ANR监测的正确姿势还是要需要做AOP,这样才能准确的监控到每一个函数的调用时间,然后做精准的定位。
目前aspectJ已经做的很好,做这个完全是一个非常方便的事情,可以慎重考虑一下~~

Exception thrown by ANR WatchDog not catchable by ACRA

Hi,

I was trying to use ANR WatchDog and ACRA to catch a bug, but when the ANR WatchDog triggers, ACRA doesn't actually catch the exception, but throws an error itself and therefore hands off the exception to the system, which then promptly kills the app. The error seems to be related to ACRA trying to serialize the exception generated by ANR WatchDog (see below).

I am using ACRA 4.8.2, and ANR WatchDog 1.1.*.

Any help would be greatly appreciated. Thanks!

03-07 17:52:43.984 18923-18953/ch.ione.safefingerprint E/ACRA: ACRA caught a ANRError for ch.ione.safefingerprint
                                                               com.github.anrwatchdog.ANRError: Application Not Responding
                                                               Caused by: com.github.anrwatchdog.ANRError$$$_Thread: main
                                                                   at android.os.BinderProxy.transactNative(Native Method)
                                                                   at android.os.BinderProxy.transact(Binder.java)
                                                                   at de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method)
                                                                   at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:681)
                                                                   at android.os.BinderProxy.transact(<Xposed>)
                                                                   at com.fingerprint.service.IFingerprintService$Stub$Proxy.open(IFingerprintService.java:259)
                                                                   at com.fingerprint.service.FingerprintManager.<init>(FingerprintManager.java:102)
                                                                   at com.fingerprint.service.FingerprintManager.open(FingerprintManager.java:149)
                                                                   at ch.ione.safefingerprint.fingerprint.FingerprintFPCImpl.getIds(FingerprintFPCImpl.java:91)
                                                                   at ch.ione.safefingerprint.fingerprint.FingerprintDelegate.getIds(FingerprintDelegate.java:53)
                                                                   at ch.ione.safefingerprint.service.FingerprintAuthenticationService.getIds(FingerprintAuthenticationService.java:252)
                                                                   at ch.ione.safefingerprint.ui.fragments.ManageFingerprintsFragment.updateFingerprintList(ManageFingerprintsFragment.java:205)
                                                                   at ch.ione.safefingerprint.ui.fragments.ManageFingerprintsFragment.access$100(ManageFingerprintsFragment.java:29)
                                                                   at ch.ione.safefingerprint.ui.fragments.ManageFingerprintsFragment$6.onServiceConnected(ManageFingerprintsFragment.java:118)
                                                                   at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java)
                                                                   at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java)
                                                                   at android.os.Handler.handleCallback(Handler.java)
                                                                   at android.os.Handler.dispatchMessage(Handler.java)
                                                                   at android.os.Looper.loop(Looper.java)
                                                                   at android.app.ActivityThread.main(ActivityThread.java)
                                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                                   at java.lang.reflect.Method.invoke(Method.java:372)
                                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
                                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
                                                                   at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:117)
                                                                Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerDaemon
                                                                   at java.lang.Object.wait(Native Method)
                                                                   at java.lang.Object.wait(Object.java:422)
                                                                   at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:101)
                                                                   at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:72)
                                                                   at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:173)
                                                                   at java.lang.Thread.run(Thread.java:818)
                                                                Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerWatchdogDaemon
                                                                   at java.lang.Object.wait(Native Method)
                                                                   at java.lang.Daemons$FinalizerWatchdogDaemon.waitForObject(Daemons.java:239)
                                                                   at java.lang.Daemons$FinalizerWatchdogDaemon.run(Daemons.java:211)
                                                                   at java.lang.Thread.run(Thread.java:818) 
                                                                Caused by: com.github.anrwatchdog.ANRError$$$_Thread: GCDaemon
                                                                   at java.lang.Object.wait(Native Method)
                                                                   at java.lang.Daemons$GCDaemon.run(Daemons.java:341)
                                                                   at java.lang.Thread.run(Thread.java:818) 
                                                                Caused by: com.github.anrwatchdog.ANRError$$$_Thread: HeapTrimmerDaemon
                                                                   at java.lang.Object.wait(Native Method)
                                                                   at java.lang.Daemons$HeapTrimmerDaemon.run(Daemons.java:310)
                                                                   at java.lang.Thread.run(Thread.java:818) 
                                                                Caused by: com.github.anrwatchdog.ANRError$$$_Thread: ReferenceQueueDaemon
                                                                   at java.lang.Object.wait(Native Method)
                                                                   at java.lang.Daemons$ReferenceQueueDaemon.run(Daemons.java:133)
                                                                   at java.lang.Thread.run(Thread.java:818) 
                                                                Caused by: com.github.anrwatchdog.ANRError$$$_Thread: |ANR-WatchDog|
                                                                   at dalvik.system.VMStack.getThreadStackTrace(Native Method)
                                                                   at java.lang.Thread.getStackTrace(Thread.java:580)
                                                                   at java.lang.Thread.getAllStackTraces(Thread.java:522)
                                                                   at com.github.anrwatchdog.ANRError.New(ANRError.java:80)
                                                                   at com.github.anrwatchdog.ANRWatchDog.run(ANRWatchDog.java:175)
03-07 17:52:44.094 18923-18953/ch.ione.safefingerprint E/ACRA: ACRA failed to capture the error - handing off to native error reporter
                                                               java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.github.anrwatchdog.ANRError)
                                                                   at android.os.Parcel.writeSerializable(Parcel.java)
                                                                   at android.os.Parcel.writeValue(Parcel.java)
                                                                   at android.os.Parcel.writeArrayMapInternal(Parcel.java)
                                                                   at android.os.BaseBundle.writeToParcelInner(BaseBundle.java)
                                                                   at android.os.Bundle.writeToParcel(Bundle.java)
                                                                   at android.os.Parcel.writeBundle(Parcel.java)
                                                                   at android.content.Intent.writeToParcel(Intent.java)
                                                                   at android.os.Parcel.writeTypedArray(Parcel.java)
                                                                   at android.app.ActivityManagerProxy.getIntentSender(ActivityManagerNative.java)
                                                                   at android.app.PendingIntent.getActivity(PendingIntent.java)
                                                                   at android.app.PendingIntent.getActivity(PendingIntent.java)
                                                                   at org.acra.builder.ReportExecutor.createNotification(ReportExecutor.java:335)
                                                                   at org.acra.builder.ReportExecutor.execute(ReportExecutor.java:196)
                                                                   at org.acra.builder.ReportBuilder.build(ReportBuilder.java:144)
                                                                   at org.acra.ErrorReporter.uncaughtException(ErrorReporter.java:259)
                                                                   at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
                                                                   at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
                                                                Caused by: java.io.NotSerializableException: com.github.anrwatchdog.ANRError$$
                                                                   at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1344)
                                                                   at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1651)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1497)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1461)
                                                                   at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:959)
                                                                   at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:360)
                                                                   at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1054)
                                                                   at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1384)
                                                                   at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1651)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1497)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1461)
                                                                   at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:959)
                                                                   at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:360)
                                                                   at java.lang.Throwable.writeObject(Throwable.java:436)
                                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                                   at java.lang.reflect.Method.invoke(Method.java:372)
                                                                   at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1033)
                                                                   at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1384)
                                                                   at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1651)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1497)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1461)
                                                                   at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:959)
                                                                   at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:360)
                                                                   at java.lang.Throwable.writeObject(Throwable.java:436)
                                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                                   at java.lang.reflect.Method.invoke(Method.java:372)
                                                                   at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1033)
                                                                   at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1384)
                                                                   at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1651)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1497)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1461)
                                                                   at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:959)
                                                                   at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:360)
                                                                   at java.lang.Throwable.writeObject(Throwable.java:436)
                                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                                   at java.lang.reflect.Method.invoke(Method.java:372)
                                                                   at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1033)
                                                                   at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1384)
                                                                at java.io.ObjectOutputStream.writeObjectInternal(
03-07 17:52:44.094 18923-18953/ch.ione.safefingerprint I/ACRA: ACRA is disabled for ch.ione.safefingerprint - forwarding uncaught Exception on to default ExceptionHandler
03-07 17:52:44.095 18923-18953/ch.ione.safefingerprint E/AndroidRuntime: FATAL EXCEPTION: |ANR-WatchDog|
                                                                         Process: ch.ione.safefingerprint, PID: 18923
                                                                         com.github.anrwatchdog.ANRError: Application Not Responding
                                                                         Caused by: com.github.anrwatchdog.ANRError$$$_Thread: main
                                                                             at android.os.BinderProxy.transactNative(Native Method)
                                                                             at android.os.BinderProxy.transact(Binder.java)
                                                                             at de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method)
                                                                             at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:681)
                                                                             at android.os.BinderProxy.transact(<Xposed>)
                                                                             at com.fingerprint.service.IFingerprintService$Stub$Proxy.open(IFingerprintService.java:259)
                                                                             at com.fingerprint.service.FingerprintManager.<init>(FingerprintManager.java:102)
                                                                             at com.fingerprint.service.FingerprintManager.open(FingerprintManager.java:149)
                                                                             at ch.ione.safefingerprint.fingerprint.FingerprintFPCImpl.getIds(FingerprintFPCImpl.java:91)
                                                                             at ch.ione.safefingerprint.fingerprint.FingerprintDelegate.getIds(FingerprintDelegate.java:53)
                                                                             at ch.ione.safefingerprint.service.FingerprintAuthenticationService.getIds(FingerprintAuthenticationService.java:252)
                                                                             at ch.ione.safefingerprint.ui.fragments.ManageFingerprintsFragment.updateFingerprintList(ManageFingerprintsFragment.java:205)
                                                                             at ch.ione.safefingerprint.ui.fragments.ManageFingerprintsFragment.access$100(ManageFingerprintsFragment.java:29)
                                                                             at ch.ione.safefingerprint.ui.fragments.ManageFingerprintsFragment$6.onServiceConnected(ManageFingerprintsFragment.java:118)
                                                                             at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java)
                                                                             at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java)
                                                                             at android.os.Handler.handleCallback(Handler.java)
                                                                             at android.os.Handler.dispatchMessage(Handler.java)
                                                                             at android.os.Looper.loop(Looper.java)
                                                                             at android.app.ActivityThread.main(ActivityThread.java)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at java.lang.reflect.Method.invoke(Method.java:372)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
                                                                             at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:117)
                                                                          Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerDaemon
                                                                             at java.lang.Object.wait(Native Method)
                                                                             at java.lang.Object.wait(Object.java:422)
                                                                             at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:101)
                                                                             at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:72)
                                                                             at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:173)
                                                                             at java.lang.Thread.run(Thread.java:818)
                                                                          Caused by: com.github.anrwatchdog.ANRError$$$_Thread: FinalizerWatchdogDaemon
                                                                             at java.lang.Object.wait(Native Method)
                                                                             at java.lang.Daemons$FinalizerWatchdogDaemon.waitForObject(Daemons.java:239)
                                                                             at java.lang.Daemons$FinalizerWatchdogDaemon.run(Daemons.java:211)
                                                                             at java.lang.Thread.run(Thread.java:818) 
                                                                          Caused by: com.github.anrwatchdog.ANRError$$$_Thread: GCDaemon
                                                                             at java.lang.Object.wait(Native Method)
                                                                             at java.lang.Daemons$GCDaemon.run(Daemons.java:341)
                                                                             at java.lang.Thread.run(Thread.java:818) 
                                                                          Caused by: com.github.anrwatchdog.ANRError$$$_Thread: HeapTrimmerDaemon
                                                                             at java.lang.Object.wait(Native Method)
                                                                             at java.lang.Daemons$HeapTrimmerDaemon.run(Daemons.java:310)
                                                                             at java.lang.Thread.run(Thread.java:818) 
                                                                          Caused by: com.github.anrwatchdog.ANRError$$$_Thread: ReferenceQueueDaemon
                                                                             at java.lang.Object.wait(Native Method)
                                                                             at java.lang.Daemons$ReferenceQueueDaemon.run(Daemons.java:133)
                                                                             at java.lang.Thread.run(Thread.java:818) 
                                                                          Caused by: com.github.anrwatchdog.ANRError$$$_Thread: |ANR-WatchDog|
                                                                             at dalvik.system.VMStack.getThreadStackTrace(Native Method)
                                                                             at java.lang.Thread.getStackTrace(Thread.java:580)
                                                                             at java.lang.Thread.getAllStackTraces(Thread.java:522)
                                                                             at com.github.anrwatchdog.ANRError.New(ANRError.java:80)
                                                                             at com.github.anrwatchdog.ANRWatchDog.run(ANRWatchDog.java:175)

ANR-WatchDog not works with Fabric(Crashlytics)

Hello,
I've implemented WatchDog in my project. But it has some problem with Fabric.
I catched the error then sent ANR error to Fabric but it seem not work

        new ANRWatchDog().setANRListener(new ANRWatchDog.ANRListener() {

            @Override
            public void onAppNotResponding(ANRError arg0) {
                   Crashlytics.getInstance().core.logException(arg0);
            }
        }).start();

Set Thread priority below main thread.

Currently, both the ANR watchdog thread and main thread has the same nice value. Add the following line at the start of the run() function to resolve the issue.

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)

Screenshot 2022-03-07 at 2 30 01 PM

Caught Exceptions having error object from ANRWatchDog not getting logged on Crashlytics Dashboard

Hi,

I am using ANRWatchDog to catch ANRs. It provides an 'error' object which I am logging to crashlytics. I am getting report upload complete logs for crashlytics but nothing appears on dashboard. Crashlytics is working fine at the same time for other types of caught/uncaught exceptions.

private ANRListener listener = new ANRListener() {
@OverRide
public void onAppNotResponding(ANRError error) {
try{
Crashlytics.logException(error);

        } catch (Exception e) {
            Logger.e(TAG, "Exception while sending ANR stacktrace to Crash reporter "+e.getStackTrace());
        }

    }
};

I have raised the issue with Crashlytics team as well. Wanted to know here if any known issue exists in ANRWatchDog.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.