반응형
🛠 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,...))
반응형
'모바일 앱(안드로이드)' 카테고리의 다른 글
| ⌚ Wear OS | 센서 수명주기·권한·동기화 연결로 기본 데이터 파이프 완성 (2) | 2025.12.05 |
|---|---|
| 🛰️ Android | 워치-폰 동기화 + 위치(x,y,z)+고도 융합(칼만/EMA) 기능 통합 작업 기록 (0) | 2025.12.03 |
| 🖐 Wear OS | 폰-워치 동기화와 큰절 제스처 시작 표식, 설정 화면 표시까지 (0) | 2025.11.29 |
| 🛠 Android | Coupang API + Hilt DI + AdsScreen UX/포맷 개선 작업 기록 (1) | 2025.11.25 |
| 🦾 Android | 하단 바 + Navigation Compose + 보안 키 주입(ResValue) 적용기 (1) | 2025.11.23 |