2026/05/07

오늘의 이야기

 


 


🛠 Wear + Phone Altitude 동기화 & 설정화면 컴파일 오류 해결 요약


워치이미지



 


개요 (Intro)



  • 오늘의 목표: 고도(Altitude) 측정 데이터 Wear→Phone 실시간 전송, 설정 화면에 단위/최근 갱신 시각 표시, SegmentedButton 컴파일 오류 해결

  • 배경: 기존 Steps 동기화는 동작하지만 고도 및 제스처(큰절) 인식 흐름 표시 요소 부족 + Material3 실험 API로 인해 빌드 실패

  • 사용 기술 스택: Kotlin, Jetpack Compose (Material3), Hilt, Health Connect, Health Services, Wearable Data/Message API, Sensor API


📅 날짜: 2025.12.01
🎯 목표: Altitude 실시간 반영 + SettingsScreen 안정화 + Wear/Phone namespace 정렬
🧰 기술: Kotlin, Compose, Hilt, Wear OS, Health Connect, Sensors, DataClient/MessageClient

문제 정의 (Problem / Motivation)



  • SettingsScreen에서 Material3 SegmentedButton 관련 심볼(Unresolved reference)로 컴파일 실패

  • Wear AVD에서 가속도/고도 센서 이벤트가 들어오지 않아 실측값 테스트 어려움

  • 고도 전송 이후 Phone UI에서 최근 갱신 시각을 안정적으로 식별할 상태 변수가 부재

  • Namespace / ApplicationId를 Phone과 Wear 간 통일 필요 (데이터 교환 및 추적 용이)


// (오류 예시) SegmentedButtonRow 미존재로 컴파일 실패
// implementation(libs.androidx.compose.material3) 버전에서 제공 안 됨
SegmentedButtonRow { /* ... */ } // Unresolved reference

해결 과정 (How I Solved It)



  • 고도 수신을 위한 ViewModel 상태 추가: altitudeMeters, altitudeTimestamp (StateFlow)

  • WearDataSyncManager.Listener에 onAltitudeUpdate(...) 콜백 정의하여 Phone 측 반영

  • SettingsScreen: 실험적 SegmentedButton 제거 → Button + OutlinedButton 토글 구현

  • 최근 갱신 시각: altitudeTimestamp 우선, 없으면 마지막 steps 페이로드 timestamp 폴백

  • 에뮬레이터 한계 대응: 실제 센서 없을 경우 ‘-’ 출력 및 Mock 옵션 향후 추가 계획 수립

  • Wear 모듈 build.gradle.kts에 compose.compiler 및 namespace=phone 앱 동일 값 적용


// ViewModel 고도 상태 및 리스너 발췌
private val _altitudeMeters = MutableStateFlow<Double?>(null)
val altitudeMeters: StateFlow<Double?> = _altitudeMeters
private val _altitudeTimestamp = MutableStateFlow<Long?>(null)
val altitudeTimestamp: StateFlow<Long?> = _altitudeTimestamp

wearDataSyncManager.listener = object : WearDataSyncManager.Listener {
override fun onAltitudeUpdate(altitudeMeters: Double, timestamp: Long, source: String) {
_altitudeMeters.value = altitudeMeters
_altitudeTimestamp.value = timestamp
}
// ... steps, gesture 등 다른 콜백
}

// SettingsScreen 고도 단위 토글 (Button / OutlinedButton)
Row {
Text("고도 단위: ")
if (unit == "m") {
Button(onClick = { unit = "m" }) { Text("m") }
OutlinedButton(onClick = { unit = "ft" }) { Text("ft") }
} else {
OutlinedButton(onClick = { unit = "m" }) { Text("m") }
Button(onClick = { unit = "ft" }) { Text("ft") }
}
}

결과 (Result)



  • 빌드 실패 원인이었던 SegmentedButton 관련 심볼 제거 후 컴파일 성공

  • 고도 실시간 값 및 최근 갱신 시각 UI 노출 로직 정상 반영 (실기기 테스트 필요)

  • Wear/Phone 동일 namespace & applicationId 적용으로 코드/로그 추적 용이

  • 제스처 인식 시작/종료 UI 명확해져 사용자 경험 개선


✅ SettingsScreen 컴파일 오류 제거
✅ Altitude 실시간 상태 흐름(StateFlow) 구축
⚠️ AVD 센서 미동작: 실제 기기 테스트 대기

느낀 점 / 회고 (Reflection)



  • 실험적 Compose API는 버전 호환을 먼저 확인해야 낭비 시간을 줄일 수 있다.

  • 센서 기반 기능은 에뮬레이터 한계가 커서 Mock/실기기 병행 전략이 필수.

  • 데이터 전송 시 timestamp를 분리 관리하면 UI 표시/디버깅이 훨씬 명확해진다.

  • 단위 토글을 단순화하니 유지보수성과 접근성이 모두 향상되었다.


참고자료 (References)





다음 개선 아이디어



  • Mock 센서 토글 추가 (AVD에서 흐름 검증)

  • Altitude smoothing (이동평균) & 최소 전송 간격 조정

  • 큰절 인식 정확도 향상을 위한 패턴 분석/버퍼링

  • Locale 안전한 숫자 포맷 적용 (String.format(Locale,...))





댓글 없음:

댓글 쓰기

오늘의 이야기

#스하리1000명프로젝트 오늘 내가 만든앱 하나 알려주고 싶어, 이 앱은 알림수집기 라고 이름을 붙였는 데, 내 폰에 표시 되는 알림을 읽어서 내가 지정한 단어가 들어 있고, 지출기록을 남겨야 하는 알림이 있으면 수집하고, 카카오톡으로 친구에게...