해결됐다고 하니 다행이네요 🙂
말해주신 케이스들(스크롤/알림바/동시 타이머/보조 타이머 정리)은 실제로 앱에서 자주 “간헐적”으로 터지는 타입이라, 원인 잡고 안정화하는 게 더 어려운 편인데 깔끔하게 정리됐습니다.

혹시 나중에 또 비슷한 이슈가 생기면, 이런 로그만 하나 찍어두면 원인 찾는 속도가 확 빨라져요:

  • 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개:
    1. 종료 시점 stale RUNNING 브로드캐스트로 인한 알람 재등록/취소 흔들림
    2. 알람 종료 시 MediaPlayer 정리 순서/idempotent 처리

원하시면 제가 프로젝트 기준으로 어느 파일(ClockService/TimerFragment/AlarmService)의 어떤 함수에 가드를 넣을지를 “정확히 코드 단위”로 적어드릴게요.
지금 zip의 패키지 구조에서 알람 재생을 담당하는 클래스가 com.krdonon.timer.alarm.AlarmService 맞죠? (이 파일에서 MediaPlayer를 만들고 종료하는 지점을 지정해주면, 그 부분을 기준으로 수정안을 바로 드리겠습니다.)

 


네. 지금 상태(“동작에 문제 없어 보임”, 크래시 없음)라면 코드를 당장 안 고쳐도 됩니다.

다만 “안 고쳐도 괜찮은지”를 판단할 때 기준이 있어요. 로그에서 제가 짚었던 건 치명 버그가 아니라 품질/안정성 개선 포인트였거든요.


안 고쳐도 되는 이유

  • 당신이 뽑은 PID 로그(11105) 기준으로 FATAL EXCEPTION / AndroidRuntime 같은 크래시가 없음
  • 알람 화면 표시/종료 흐름이 정상
  • “Force stop” 이슈도 실사용(AAB 설치)에서는 events 로그에 안 찍혔다고 하셨으니, 개발툴(스튜디오 배포) 노이즈였을 가능성이 큼

즉, 현재 사용자 경험에 문제가 없으면 그대로 출시/사용해도 됩니다.


그래도 고치면 좋은 이유(하지만 선택사항)

제가 본 2가지 포인트는 이런 리스크를 낮춥니다:

  1. 종료 직후 늦게 도착한 RUNNING 이벤트(스테일 브로드캐스트)
    • 대부분은 “순간 UI 흔들림/로그 중복” 정도로 끝나지만
    • 운 나쁘면 알람 등록/취소 타이밍이 꼬여서 “가끔 이상하게 동작” 같은 희귀 버그로 이어질 수는 있음
  2. MediaPlayer 정리 경고
    • 지금은 경고로 끝날 확률이 높지만
    • 특정 기기/OS에서 “가끔 소리 끊김/리소스 누수”로 번질 수 있는 타입이라, 깔끔히 정리해두면 장기적으로 안전

하지만 둘 다 지금 당장 반드시 고쳐야 하는 레벨은 아닙니다.


“이 경우엔 고치세요” 체크리스트

아래 중 하나라도 겪으면 그때는 수정 권장입니다.

  • 알람이 가끔 안 꺼지거나, 껐는데도 다시 소리가 난다
  • 알람 종료 시 소리가 끊기지 않고 남는다 / 진동이 남는다
  • 타이머 종료 순간 UI가 RUNNING↔STOPPED로 “깜빡”하는 게 눈에 띈다
  • 특정 기기에서만 알람이 2번 울리거나 알림이 중복됨
  • 장시간 반복 사용 후 앱이 느려지거나 오디오 관련 이상이 생김

이런 증상이 없으면 “현상 유지”가 합리적이에요.


추천 결론

  • 지금은 그대로 두셔도 OK
  • 다만 다음 릴리즈 때 여유 있을 때, 제가 말한 2개(스테일 RUNNING 가드 + MediaPlayer 정리 idempotent)만 정리하면 로그도 깨끗해지고 희귀 버그 가능성도 줄어듭니다.

원하시면 “최소 수정(딱 10~20줄 수준)”으로 안전성만 올리는 형태로, 어느 파일의 어느 함수에 넣으면 되는지 아주 간단히 정리해서 드릴게요.

반응형

+ Recent posts