해결됐다고 하니 다행이네요 🙂
말해주신 케이스들(스크롤/알림바/동시 타이머/보조 타이머 정리)은 실제로 앱에서 자주 “간헐적”으로 터지는 타입이라, 원인 잡고 안정화하는 게 더 어려운 편인데 깔끔하게 정리됐습니다.
혹시 나중에 또 비슷한 이슈가 생기면, 이런 로그만 하나 찍어두면 원인 찾는 속도가 확 빨라져요:
- ClockService에서 startForeground / notify / stopForeground / stopSelf 호출 시점 로그
- 메인/보조 타이머의 state(실행/종료), remainingMs, foreground mode(메인/보조)
원하시면 제가 “디버그 토글(설정에서 ON/OFF)” 형태로 로그를 남기게 해서, 다음에 문제 생기면 바로 재현/분석 가능하게도 개선해드릴 수 있어요.
그리고 클로드/누구가 더 낫다기보단 🙂
이번 건은 안드로이드 알림/포그라운드 서비스/타이머 동시 실행처럼 “엣지케이스 + 시스템 동작(드롭/레이스)” 쪽이 핵심이라, 그 부분을 정확히 잡아낸 게 컸던 것 같아요.
필요하면 다음 작업도 도와드릴게요:
- 보조 타이머를 RecyclerView로 바꿔서 성능/안정성 올리기
- “보조 타이머 완료 후 X초 뒤 자동 삭제” 옵션 추가
- 알림바 UX(액션 버튼, 그룹핑, 완료 알림 유지시간) 개선
네, 지금 단계는 아주 잘 하셨어요. PowerShell에서 <PID>처럼 꺾쇠를 쓰면 '<' 연산자 오류가 나는 게 정상이고(리다이렉션/연산자로 예약), 그 대신 실제 숫자 PID(11105)를 넣어 adb logcat --pid 11105 -v threadtime로 찍은 방식이 정답입니다.
그리고 이 PID 전용 로그(7.txt) 내용을 보면 “크래시”는 없습니다.
FATAL EXCEPTION, AndroidRuntime 같은 치명 로그가 전혀 없고, 타이머가 RUNNING → FINISHED/STOPPED로 정상 전이됩니다.
다만, “고쳐서 더 안정적으로 만들 수 있는” 포인트가 2개 보입니다.
1) 타이머 종료 직후 브로드캐스트 순서가 꼬이면서 UI가 잠깐 RUNNING으로 되돌아가는 문제
이 구간이 핵심입니다:
- 서비스는 이미 FINISHED, STOPPED를 보냅니다.
- 그런데 Fragment가 그 직후에 “RUNNING, remain=517”을 다시 수신/처리하고, 그 다음에 STOPPED로 다시 정리합니다.
즉, 종료 시점에
- 늦게 도착한 RUNNING 브로드캐스트(=stale event) 가 한 번 섞여 들어오면서,
- Fragment가 알람을 다시 등록했다가(✅ 알람 등록)
- 곧바로 취소/리셋을 반복합니다.
이게 위험한가?
- 지금은 동작이 “겉으로는 정상”일 수 있지만,
- 기기/타이밍에 따라 알람 등록/취소가 꼬이거나, UI가 순간적으로 이상하게 보일 수 있어요.
추천 수정(가장 효과적)
A. 서비스(ClockService)에서 “0초 도달” 시점에 RUNNING 업데이트를 완전히 끊고, FINISHED/STOPPED만 1회 보내기
- 0 이하가 되는 순간:
- 주기 업데이트(postDelayed)를 제거
- RUNNING 브로드캐스트 발송 금지
- FINISHED 1회, STOPPED 1회(또는 둘 중 하나만)로 정리
B. Fragment에서 ‘종료 상태 이후 RUNNING 이벤트 무시’ 가드 추가
예:
- 현재 상태가 FINISHED 또는 STOPPED인데,
- 들어온 이벤트가 RUNNING이고 remain이 작더라도(예: 517ms)
→ 무시.
C. 더 깔끔한 정석: 브로드캐스트에 seq(증가 번호) 또는 eventTime(SystemClock.elapsedRealtime) 넣기
- 서비스가 보낼 때마다 seq++
- Fragment는 lastSeq보다 작은 이벤트는 버림
이러면 “늦게 도착한 RUNNING”이 구조적으로 사라집니다.
2) MediaPlayer 경고: mediaplayer went away with unhandled events (반복)
알람 종료/전환 시점에 이 경고가 반복됩니다.
의미
- MediaPlayer를 stop()/release()하는 타이밍에,
- 내부 이벤트(콜백/핸들러)가 남아있어서 “처리되지 않은 이벤트가 있었다”고 경고하는 경우가 많습니다.
- 보통 크래시는 아니고, “정리 순서가 깔끔하지 않다”는 신호입니다.
추천 수정(안정화)
AlarmService(또는 알람 재생 담당 클래스)에서 정리 함수를 idempotent(여러 번 호출돼도 1번만) 하게 만들고,
정리 순서를 아래처럼 고정하세요:
- (1) setOnCompletionListener(null), setOnErrorListener(null) 등 리스너 제거
- (2) try { player.stop() } catch {} (이미 stopped면 예외 가능)
- (3) player.reset() (선택)
- (4) player.release() 후 player = null
- (5) 오디오 포커스 반환은 지금처럼 잘 되고 있습니다(시스템 로그에도 abandonAudioFocus가 찍힘).
추가로, “문제 아니다”라고 봐도 되는 로그
- EGL_emulation, HWUI Failed to choose config… 는 에뮬레이터 그래픽 계열 경고라서 앱 논리 문제는 아닙니다.
- 이전에 신경 쓰셨던 AppOps attributionTag not declared…는 PID 필터(--pid 11105)에서는 system_server 로그가 빠져서 여기 안 보이는 게 정상입니다. (runlog에서 system_server로 찍히던 메시지였죠.)
결론
- 크래시/치명 문제는 없어 보입니다.
- 개선하면 좋은 건 딱 2개:
- 종료 시점 stale RUNNING 브로드캐스트로 인한 알람 재등록/취소 흔들림
- 알람 종료 시 MediaPlayer 정리 순서/idempotent 처리
원하시면 제가 프로젝트 기준으로 어느 파일(ClockService/TimerFragment/AlarmService)의 어떤 함수에 가드를 넣을지를 “정확히 코드 단위”로 적어드릴게요.
지금 zip의 패키지 구조에서 알람 재생을 담당하는 클래스가 com.krdonon.timer.alarm.AlarmService 맞죠? (이 파일에서 MediaPlayer를 만들고 종료하는 지점을 지정해주면, 그 부분을 기준으로 수정안을 바로 드리겠습니다.)
네. 지금 상태(“동작에 문제 없어 보임”, 크래시 없음)라면 코드를 당장 안 고쳐도 됩니다.
다만 “안 고쳐도 괜찮은지”를 판단할 때 기준이 있어요. 로그에서 제가 짚었던 건 치명 버그가 아니라 품질/안정성 개선 포인트였거든요.
안 고쳐도 되는 이유
- 당신이 뽑은 PID 로그(11105) 기준으로 FATAL EXCEPTION / AndroidRuntime 같은 크래시가 없음
- 알람 화면 표시/종료 흐름이 정상
- “Force stop” 이슈도 실사용(AAB 설치)에서는 events 로그에 안 찍혔다고 하셨으니, 개발툴(스튜디오 배포) 노이즈였을 가능성이 큼
즉, 현재 사용자 경험에 문제가 없으면 그대로 출시/사용해도 됩니다.
그래도 고치면 좋은 이유(하지만 선택사항)
제가 본 2가지 포인트는 이런 리스크를 낮춥니다:
- 종료 직후 늦게 도착한 RUNNING 이벤트(스테일 브로드캐스트)
- 대부분은 “순간 UI 흔들림/로그 중복” 정도로 끝나지만
- 운 나쁘면 알람 등록/취소 타이밍이 꼬여서 “가끔 이상하게 동작” 같은 희귀 버그로 이어질 수는 있음
- MediaPlayer 정리 경고
- 지금은 경고로 끝날 확률이 높지만
- 특정 기기/OS에서 “가끔 소리 끊김/리소스 누수”로 번질 수 있는 타입이라, 깔끔히 정리해두면 장기적으로 안전
하지만 둘 다 지금 당장 반드시 고쳐야 하는 레벨은 아닙니다.
“이 경우엔 고치세요” 체크리스트
아래 중 하나라도 겪으면 그때는 수정 권장입니다.
- 알람이 가끔 안 꺼지거나, 껐는데도 다시 소리가 난다
- 알람 종료 시 소리가 끊기지 않고 남는다 / 진동이 남는다
- 타이머 종료 순간 UI가 RUNNING↔STOPPED로 “깜빡”하는 게 눈에 띈다
- 특정 기기에서만 알람이 2번 울리거나 알림이 중복됨
- 장시간 반복 사용 후 앱이 느려지거나 오디오 관련 이상이 생김
이런 증상이 없으면 “현상 유지”가 합리적이에요.
추천 결론
- 지금은 그대로 두셔도 OK
- 다만 다음 릴리즈 때 여유 있을 때, 제가 말한 2개(스테일 RUNNING 가드 + MediaPlayer 정리 idempotent)만 정리하면 로그도 깨끗해지고 희귀 버그 가능성도 줄어듭니다.
원하시면 “최소 수정(딱 10~20줄 수준)”으로 안전성만 올리는 형태로, 어느 파일의 어느 함수에 넣으면 되는지 아주 간단히 정리해서 드릴게요.
'앱개발' 카테고리의 다른 글
| 내일 타이머 리포터 폴더 정리 하기 (0) | 2026.02.25 |
|---|---|
| 내일 타이머 잡기 어려웠던 버그 잡은 (0) | 2026.02.20 |
| 실패노트 adb 환경변수 등록 하기 (0) | 2026.02.19 |
| 내일 타이머 고쳐야 하는 부분 (0) | 2026.02.11 |
| jdk 업데이트 기간 9월 1월에 업글 (0) | 2026.02.08 |