Android ANR(애플리케이션 응답 없음)을 감지하는 간단한 감시 장치입니다.
현재 Android 애플리케이션에서 ANR 오류를 포착하고 보고할 수 있는 방법은 없습니다.
애플리케이션이 Play 스토어에 없는 경우(아직 개발 중이거나 다르게 배포하기 때문에) ANR을 조사하는 유일한 방법은 /data/anr/traces.txt 파일을 가져오는 것입니다.
또한 Play 스토어를 사용하는 것이 자체 버그 추적 서비스를 선택하는 것만큼 효과적이지 않다는 사실을 발견했습니다.
Android 버그 추적기에 이러한 부족함을 설명하는 문제 항목이 있습니다. 별표를 표시해 주세요. ;)
UI 스레드가 응답을 중지하는 시점을 감지하는 "watchdog" 타이머를 설정합니다. 그렇게 되면 모든 스레드 스택 추적(기본 우선)에 오류가 발생합니다.
예! 질문해주셔서 기쁩니다. 그것이 애초에 개발된 이유입니다!
이로 인해 오류가 발생하면 충돌 처리기가 이를 가로채서 필요한 방식으로 처리할 수 있습니다.
알려진 작업 충돌 보고자는 다음과 같습니다.
setReportMainThreadOnly()
에만 해당)그리고 [여기에 즐겨 사용하는 충돌 보고 시스템 삽입] 과 함께 작동하지 않을 이유가 없습니다.
Watchdog은 루프에서 다음을 수행하는 간단한 스레드입니다.
app/build.gradle
파일에 다음을 추가합니다.
implementation 'com.github.anrwatchdog:anrwatchdog:1.4.0'
애플리케이션 클래스의 onCreate
에 다음을 추가합니다.
new ANRWatchDog (). start ();
최신 jar 다운로드
프로젝트의 libs/
디렉토리에 jar를 넣으세요.
ANRError
스택 추적은 약간 특별하며, 애플리케이션에서 실행 중인 모든 스레드의 스택 추적을 포함합니다. 따라서 보고서에서 섹션 caused by
각각은 이전 예외의 원인이 아니라 다른 스레드의 스택 추적입니다.
다음은 교착 상태의 예입니다.
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)
이 보고서를 통해 두 스레드의 스택 추적을 확인할 수 있습니다. 첫 번째("기본" 스레드)는 MainActivity.java:46
에 멈춰 있는 반면 두 번째 스레드("App: Locker")는 MainActivity.java:18
의 Sleep 모드에 잠겨 있습니다.
거기에서 이 두 줄을 보면 교착 상태의 원인을 확실히 이해할 수 있을 것입니다!
일부 충돌 보고 라이브러리(예: Crashlytics)는 포착되지 않은 예외 발생 시 모든 스레드 스택 추적을 보고합니다. 이 경우 동일한 예외에 모든 스레드를 두는 것은 번거로울 수 있습니다. 이러한 경우에는 간단히 setReportMainThreadOnly()
사용하세요.
다른 시간 초과를 설정하려면(기본값은 5000밀리초):
if ( BuildConfig . DEBUG == false ) {
new ANRWatchDog ( 10000 /*timeout*/ ). start ();
}
기본적으로 워치독은 디버거가 연결되어 있거나 앱이 디버거 연결을 기다리고 있는 경우 ANR을 무시합니다. 실행 일시 중지 및 중단점을 ANR로 감지하기 때문입니다. 이를 비활성화하고 디버거가 연결된 경우에도 ANRError
발생시키려면 setIgnoreDebugger(true)
추가하면 됩니다.
new ANRWatchDog (). setIgnoreDebugger ( true ). start ();
ANR이 감지될 때 애플리케이션이 충돌하지 않도록 하려면 대신 콜백을 활성화할 수 있습니다.
new ANRWatchDog (). setANRListener ( new ANRWatchDog . ANRListener () {
@ Override
public void onAppNotResponding ( ANRError error ) {
// Handle the error. For example, log it to HockeyApp:
ExceptionHandler . saveException ( error , new CrashManager ());
}
}). start ();
이는 프로덕션 환경에서 앱을 제공할 때 매우 중요합니다. 최종 사용자의 손에 있을 때 5초 후에 충돌이 발생하지 않는 것이 더 나을 것 입니다. 대신 사용하는 보고 시스템에 ANR을 보고하기만 하면 됩니다. 어쩌면 몇 초 후에 앱이 "정지 해제"될 수도 있습니다.
ANRError에 모든 스레드( FinalizerDaemon
스레드와 같은 시스템 스레드 포함)가 아닌 자체 스레드만 보고하려는 경우 접두사를 설정할 수 있습니다. 이름이 이 접두사로 시작하는 스레드만 보고됩니다. .
new ANRWatchDog (). setReportThreadNamePrefix ( "APP:" ). start ();
그런 다음 스레드를 시작할 때 이름을 이 접두사로 시작하는 것으로 설정하는 것을 잊지 마십시오(보고하려는 경우).
public class MyAmazingThread extends Thread {
@ Override
public void run () {
setName ( "APP: Amazing!" );
/* ... do amazing things ... */
}
}
다른 모든 스레드가 아닌 기본 스레드 스택 추적만 원할 경우 다음을 수행할 수 있습니다.
new ANRWatchDog (). setReportMainThreadOnly (). start ();
때로는 애플리케이션이 특정 기간 동안 정지되었음을 알고 싶지만 아직 ANR 오류를 보고하고 싶지 않은 경우가 있습니다. 오류를 보고하기 전에 호출될 인터셉터를 정의할 수 있습니다. 인터셉터의 역할은 주어진 정지 기간을 고려하여 ANR 오류를 발생시키거나 연기해야 하는지 여부를 정의하는 것입니다.
new ANRWatchDog ( 2000 ). setANRInterceptor ( new ANRWatchDog . ANRInterceptor () {
@ Override
public long intercept ( long duration ) {
long ret = 5000 - duration ;
if ( ret > 0 ) {
Log . w ( TAG , "Intercepted ANR that is too short (" + duration + " ms), postponing for " + ret + " ms." );
}
return ret ;
}
})
이 예에서 ANRWatchDog는 2000ms의 시간 초과로 시작하지만 인터셉터는 최소 5000ms의 정지 시간에 도달할 때까지 오류를 연기합니다.
ANRWatchDog는 스레드이므로 언제든지 중단할 수 있습니다.
Android의 다중 프로세스 기능(예: 새 프로세스에서 활동 시작)으로 프로그래밍하는 경우 프로세스당 ANRWatchDog 스레드가 필요하다는 점을 기억하세요.
ANR-Watchdog은 비영리 및 상업적 용도 모두 무료로 사용할 수 있으며 앞으로도 그럴 것입니다.
내 작업에 대한 지지나 감사를 표시하고 싶다면 자유롭게 기부 할 수 있습니다!
이것은 (물론) 매우 감사할 일이지만 도움이나 지원을 받기 위해 반드시 필요한 것은 아니며 기꺼이 무료로 제공하겠습니다 :)