본문 바로가기
Android 개발/Debug, ADB, CrashLytics, LogCat

WindowManager$BadTokenException 대응하기

by Developer88 2020. 2. 6.
반응형

Firebase의 CrashLytics에서 BadTokenException리포트를 받은 적이 있는데요.

오늘은 해당 Exception에 대해서 분석하고 대응해 보도록 하겠습니다.

 

1. 실제로 받은 BadTokenException

실제로 받아보았던 BadTokenException은 아래와 같은데요.

 

먼저 가운데에 at android.os.Handler.dispatchMessage(Handler.java:102)를  통해서,

Handler객체가 Toast를 보여줄려고 했었다는 것을 알 수 있습니다.

 

 

Toast를 보여주려고 하면서,

view를 윈도우매니저에 add 하려고 하는데요.

setView를 viewRoot에 하려고 하다가 BadTokenException을 받게 된 것이지요.

 

힌트를 더욱 얻기 위해서, Exception의 첫줄을 좀 더 읽어보면,

unable to add window => 윈도우를 추가할 수 없었다.

token android.os.BinderProxy@ff079cd is  not valid 이라고 나와있습니다

여기서 ff079cd는 존재하지 않아서 문제가 된 객체의 메모리 주소이구요.

 

Toast에서는 Activity로부터 Context를 인자로 받아서 실행하게 되는데요.

해당 Activity가 유저가 back버튼을 눌렀던지, 아니면 어떠한 이유로 존재하지 않는데,

Toast가 실행하려고 해서 생기는 문제이겠지요.

 

 

2. 문제 해결

위에서 Stack을 보고 문제가 무엇인지 파악해 보았습니다.

문제는 Toast를 실행할 순간에 Activity가 존재하지 않았다는 것 이지요.

유저가 Back버튼을 눌러서 인지, 혹은 코드상의 어떤 흐름때문인지는

상황에 따라 다를 것이구요.

재현이 되어서 추적할 수 있다면 더욱 좋겠지만, 재현하기 힘든 경우도 많을 것 같습니다.

 

주어진 상황은 다 다르겠지만,

이를 해결하기 위해서는 Toast에 Context를 넘겨주기전에,

Activity가 살아있는지를 판단해 보아야 하겠습니다.

 

우선은 현재 사용할 수 있는 API가 무엇인지 살펴보겠습니다.

isFinishing메소드와 API17버전부터 사용할 수 있는 isDestroyed메소드가 있는데요.

isFinishing은 지금 Activity가 destroy되는 과정에 있는지 확인하는 것 입니다.

유저가 앱을 나가버리는 순간과 Toast가 실행되는 순간의 시간차에 의해서,

Toast가 context를 받아서 실행하려고 하는 순간 바로 전에 Activity는 Destroy될 수 있겠지요.

또한 API17부터 제공하는 isDestroyed메소드는 onDestroy가 호출되었었는지를 알려주는 메소드 이구요.

 

 

우선은 이 두가지 함수로 Context가 없는상태에서 Toast가 실행되는 것을 방지해 볼 수 있을 것 같습니다

더 좋은 방법이 있다면, 이 글을 통해서 업데이트 하도록 하겠습니다.

 

728x90

댓글