diff --git a/app/src/main/java/com/medithings/vesiscan/MainActivity.kt b/app/src/main/java/com/medithings/vesiscan/MainActivity.kt index 0fda484..f6ff681 100644 --- a/app/src/main/java/com/medithings/vesiscan/MainActivity.kt +++ b/app/src/main/java/com/medithings/vesiscan/MainActivity.kt @@ -82,6 +82,28 @@ class MainActivity : ComponentActivity() { } } } + + /** + * 2026-08-12: 테스트 세션 종료 시 자동 페어링 해제 (dev-mode 용). + * + * `GreenZoneConstants.autoUnbondOnAppExit` ON 이고 · 연결된 기기가 있으면 + * `disconnectAndUnbond()` 실행 → 기기측 msr(unbond+reboot) + 폰측 removeBond. + * 다음 실행 (다른 폰) 에서 fresh pairing 가능하도록 clean state 유지. + * + * onDestroy 는 앱 강제종료 시 스킵될 수 있으나 · 정상 종료 (뒤로가기 · 홈 스와이프 + * 후 recent 앱에서 swipe away) 는 커버. dev-mode 테스트 workflow 는 대부분 정상 종료. + */ + override fun onDestroy() { + try { + if (com.medithings.vesiscan.managers.GreenZoneConstants.autoUnbondOnAppExit) { + val ble = com.medithings.vesiscan.ble.BleManager.getInstance(applicationContext) + if (ble.isConnected.value) { + ble.disconnectAndUnbond() + } + } + } catch (_: Exception) { /* silent · 종료 시점 · UC-05 */ } + super.onDestroy() + } } @Composable diff --git a/app/src/main/java/com/medithings/vesiscan/managers/GreenZoneConstants.kt b/app/src/main/java/com/medithings/vesiscan/managers/GreenZoneConstants.kt index e9aac09..9ed449e 100644 --- a/app/src/main/java/com/medithings/vesiscan/managers/GreenZoneConstants.kt +++ b/app/src/main/java/com/medithings/vesiscan/managers/GreenZoneConstants.kt @@ -71,6 +71,20 @@ object GreenZoneConstants { @Volatile var placementGuideMode: PlacementGuideMode = PlacementGuideMode.SIMPLE @Volatile var alignmentAlgo: AlignmentAlgo = AlignmentAlgo.V1 // default V1 (일반 사용자). V2 (Method D) 는 clinical alignment session 전용. + /** + * 2026-08-12: 테스트 세션 종료 시 자동 페어링 해제 (dev-mode 용). + * + * ON 시 · MainActivity.onDestroy() 에서 연결된 기기가 있으면 자동으로 + * disconnectAndUnbond() 호출. 여러 폰 × 여러 기기 테스트 환경에서 매번 수동으로 + * 페어링 해제할 필요 없이 앱 종료만 하면 기기 clean state 유지. + * + * 시나리오: 폰 A 로 기기 A 테스트 → 앱 종료 → 자동 unbond msr 전송 → + * 기기 A 는 폰 A bond 삭제 → 다음에 폰 B 가 기기 A 와 fresh pairing 성공. + * + * default OFF (일반 사용자 flow 는 bond 유지가 UX 이점 · 잘못 켜지면 매번 재페어링). + */ + @Volatile var autoUnbondOnAppExit: Boolean = false + /** Posture pitch 임계값 (deg). |pitch| > 이 값 → LYING, ≤ 이 값 → NON_LYING. dev 모드에서 조정 가능. */ @Volatile var pitchLyingThreshold: Float = 25f diff --git a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt index ab8cc79..3b2b698 100644 --- a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt +++ b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt @@ -2403,6 +2403,37 @@ fun PiezoMonitoringView(appState: AppState) { ) } + // 2026-08-12: 다중 폰 × 다중 기기 테스트 workflow 자동화 (dev-mode 전용). + // ON 시 · MainActivity.onDestroy() 에서 자동으로 disconnectAndUnbond(). + // 다음 실행 (다른 폰) 에서 fresh pairing 성공 · 매번 수동 unbond 불필요. + if (appState.isDevMode) { + Spacer(modifier = Modifier.height(6.dp)) + var autoUnbond by remember { + mutableStateOf(com.medithings.vesiscan.managers.GreenZoneConstants.autoUnbondOnAppExit) + } + Row( + modifier = Modifier.fillMaxWidth() + .background(MlPrimary.copy(alpha = 0.05f), RoundedCornerShape(10.dp)) + .padding(horizontal = 12.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Column(modifier = Modifier.weight(1f)) { + Text("앱 종료 시 자동 페어링 해제", + fontSize = 13.sp, fontWeight = FontWeight.SemiBold) + Text("[dev] 다중 폰×기기 테스트용 · 종료 시 unbond", + fontSize = 10.sp, color = MlSecondaryText) + } + Switch( + checked = autoUnbond, + onCheckedChange = { + autoUnbond = it + com.medithings.vesiscan.managers.GreenZoneConstants.autoUnbondOnAppExit = it + }, + colors = SwitchDefaults.colors(checkedTrackColor = MlPrimary), + ) + } + } + Spacer(modifier = Modifier.height(8.dp)) HorizontalDivider(modifier = Modifier.padding(vertical = dividerPadding)) Spacer(modifier = Modifier.height(8.dp))