Initial commit: VesiscanBasic Android app

Port of MedilightV2 iOS app to Android with Kotlin + Jetpack Compose.
Includes BLE connectivity, NIRS/Piezo sensor modes, Rive animations,
interactive measurement history charts, and foldable device support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 17:27:00 +09:00
commit a8532917b4
73 changed files with 5662 additions and 0 deletions
@@ -0,0 +1,50 @@
package com.example.medilightv2android.services
import android.content.Context
import androidx.compose.runtime.mutableStateOf
import com.example.medilightv2android.ble.BleManager
import com.example.medilightv2android.models.SensorMode
class MeasurementService private constructor(context: Context) {
companion object {
@Volatile
private var instance: MeasurementService? = null
fun getInstance(context: Context): MeasurementService =
instance ?: synchronized(this) {
instance ?: MeasurementService(context.applicationContext).also { instance = it }
}
}
private val bleManager = BleManager.getInstance(context)
val isMeasuring = mutableStateOf(false)
fun performMeasurement(mode: SensorMode, completion: (Boolean) -> Unit) {
isMeasuring.value = true
when (mode) {
SensorMode.NIRS -> performNirsMeasurement(completion)
SensorMode.PIEZO -> performPiezoMeasurement(completion)
}
}
private fun performNirsMeasurement(completion: (Boolean) -> Unit) {
bleManager.onNirsMcjReceived = { _ ->
isMeasuring.value = false
completion(true)
}
bleManager.sendMcjQuery()
}
private fun performPiezoMeasurement(completion: (Boolean) -> Unit) {
bleManager.onPiezoDataReceived = { _ ->
isMeasuring.value = false
completion(true)
}
bleManager.sendBurst(freqOption = 2, cycles = 5, delayUs = 100)
}
fun stop() {
isMeasuring.value = false
bleManager.sendPiezoStop()
}
}