[Android] AlarmManager 등록 여부 확인 및 주의점 (2) Feat.삽질

양현진·2022년 4월 21일
2

Oh My Android

목록 보기
5/22
post-thumbnail

Android 공식 문서대로 했다, 이해가 완벽히 안가면 관련 내용을 추가적으로 공부했다, 이젠 버그를 유발할 코드는 없다.
그런데 왜 receiver로 이벤트가 안 오는거지? 정확히는 1, 2분 뒤 등록한 알람은 이벤트가 발생하는데, 그 뒤 30분부터는 알람이 오지 않았다.

정말로 골머리를 앓았다. 아무리 AlarmManager 오류, 버그, 주의점, 안울림, Doze모드 다 검색해서 하나하나 읽어봐도 나랑 코드가 다른건 없었다. 더불어 알람 테스트 성격 상 다음날 알람을 확인하려면 하루가 걸리는 너무나도 힘든 인내의 시간이었다. 구글의 버그일까, 하지만 다른 어플들은 잘만 동작해보인다. 이건 내 실수다.

차근차근 스텝을 밟아가며 생각해봤다. 우선 첫번째로 알람이 안 울리는 이유는 알람 등록이 안 되어있을 확률이 높다.

음 너무나도 잘 되는군

일단 코드상에서 에러없이 잘 등록이 되었다. 하지만 의구심을 품었다. 등록이 되었으면 알람이 제때 울려야지!
휴대폰 내에서 정말로 등록이 되었는지 확인할 증명서가 필요했다. 방법은 터미널에다 명령어를 입력하면 등록 여부를 확인할 수 있단다.

Window OS: adb shell dumpsys alarm | findstr [패키지명] 예 - com.example.myapplication
Mac OS: adb shell dumpsys alarm | grep [패키지명] 예 - com.example.myapplication

맥은 grep으로 패키지를 찾는데 윈도우용은 없더라, grep 대신 findstr을 입력하면 된다.

터미널을 켜는 경로는
Setting -> Android SDK -> 디렉터리 복사 -> platform-tools까지 들어가서 cmd 실행

아주 등록이 잘 되어 있구만..

보는법은 위에 더 긴 결과값과 밑에 더 짧은 결과값이 나누어져 있다.
많은 테스트를 거치며 스스로 터득한 내용으로 우선 공통적인 내용부터 왼쪽에서 오른쪽 순서로 말하자면

  • BroadCastReceiver 경로

  • AC=false -> setAlarmClock이 아닌 메서드로 등록
  • AC=true -> setAlarmClock으로 등록
  • OW = 2022-04-21 10:00:00:308 -> 알람이 발생예정인 시각
  • rtc-2022-04-21 04:00:16.317 -> 알람이 등록된 시각

나는 setExactAndAllowWhileIdle을 사용하면서 반복적인 알람등록을 위해 알람이 발생하면 그 시점에 Calendar의 add메서드로 DATE + 1을 해주어 다음날에도 울리도록 했다.

아래

  • rtc-2022-04-21 09:00:40.110 -> 알람이 발생한 시각

이 정도로만 봐도 일단 충분하다. 아무튼 문제는 알람이 등록됐다는 것. 이 정도면 알람 등록에 대한 문제는 없어 보였다.
그러면 수신쪽인 Receiver에 문제가 있다고 판단했다. 하지만 Receiver클래스에서 추가적으로 더 할 수 있는건 추가적인 검색을 통해 기기의 CPU, Screen, Keyboard를 깨우는 WakeLock권한을 적용하는 것 뿐이었다. Android의 PowerManager클래스로 시도해봤지만 의미가 없어 코드는 적지 않겠다.

이 이후부턴 시간낭비었다. 같은 내용으로 1주일이 넘어가니 머리엔 포기라는 생각만 가득찼고, 꿈에도 나왔다..상당했던 스트레스

아무튼 계속 테스트를 하고 있었는데 어느 테스트 시점에서 30분 뒤 알람 등록을 했던것이 수신에 성공해 Notification이 팝업됐다.
이때 전 테스트와 다른점이 컴퓨터와 휴대폰이 케이블로 연결되어있었다. 이 이후엔 어쩌다 발견했는지 기억이 가물가물했지만 결과를 말하자면

Android Studio의 Stop(Ctrl + F2)를 실행하면 알람이 등록되었더라도 알람이 발생하지 않았다.!

나는 여태 확실한 백그라운드에서의 알람 테스트를 위해 컴퓨터와 핸드폰에 연결된 케이블을 분리하고 앱을 종료했었는데 종료하는 방식이 휴대폰에서 끄는 방식이 아닌 Android Studio의 Stop을 통해 종료시켰었다.

정상적으로 테스트를 하려면 Stop을 실행하지 말고, 그냥 앱을 단순하게 종료시키면 된다. 케이블 연결 여부는 상관이 없었다.
참 우연찮게 원인을 찾게 됐고, 자연스럽게 Stop의 실행방식에 대해 알아보려 했지만 적절한 검색 키워드를 찾지 못해 관련없는 내용만 나와 알진 못했다.

하지만 이 Stop기능이 강력한 아이인 사례를 보자면 Android의 4대 컴포넌트인 Service 중 Foreground Service를 실행하면 앱이 종료되어도 Service는 살아남는다.

하지만 여기서 앱 종료를 Stop으로 실행하게 되면 Service마저 죽게되는 현상을 보아하니 AlarmManager도 이래서 죽는건가 추측을 한다.

그 동안 별에별 발광을 떤 기억이 난다. setExactAndAllowWhileIdle를 setWindow, setAlarmClock으로 바꿔보고 PendingIntent의 Flag를 FLAG_IMMUTABLE에서 MUTABLE로도 바꿔보고 WakeLock도 해보고 휴대폰도 바꿔서 해보고 하도 많은 run때문에 앱의 문젠가 싶어 3개의 다른 프로젝트로도 실행했었다.

별로 없어보이지만 이것들 다 한번 테스트하려면 기본 2시간에서 보통 하루씩 걸리니 뇌의 주름이 다리미질 당하는 기분이었다...

성공적인 해결 이후, 그로부터 1주일이 더 지난 지금 AlarmManager의 상태를 보면 간간히 앱이 실행되지 않을때 알람이 많이 지연되는 현상이 보인다. 못참아서 앱을 실행시키면 실행과 동시에 Notification이 발생한다. 다른 앱을 실행중이니 Doze모드랑은 상관이 없어보이고 Doze모드를 깨우는 setExactAndAllowWhileIdle를 쓰는데 모르겠다. 문서에 setExactAndAllowWhileIdle이라도 최소 9분까지 지연된다하니 뭐 별수 없었다.
근데 9분보다 더 지연되는 경우가 한 번 있었는데 뭐징

Doze모드 외에 개별 앱에서 적용되는 Standby모드도 있던데 얘 때문인가 싶다.

후기

요즘 잠이 참 잘 온다

끘!

profile
Android Developer

1개의 댓글

comment-user-thumbnail
2022년 6월 14일

잘 읽었습니다 감사합니다!

답글 달기