admin管理员组文章数量:1278914
I’m working with the Samsung Health Sensor API (v1.3.0) to collect Inter-Beat Interval (IBI) data from a Galaxy Watch. My goal is to gather IBI samples periodically (e.g., every hour for 10 minutes) even when the app is not active and the screen is off. The issue I’m facing is that data collection only works when the screen is on or the app is actively running. As soon as the screen turns off or the app moves to the background, the Samsung Health Sensor API stops delivering IBI data, making it impossible to collect the necessary samples as scheduled.
I have tried using Foreground Services to keep the app running in the foreground, but the Samsung Health Sensor API still stops delivering IBI data when the screen turns off. Additionally, I implemented a Wake Lock to prevent the watch from going into a low-power state, but this did not resolve the issue either. Despite these efforts, data collection only works when the screen is on or the app is actively running. I also checked for any relevant permissions or settings that might allow continuous background data collection, but I haven't found a solution yet.
This is the worker:
class IBIDataCollectionWorker(
private val context: Context,
workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
private var healthService: HealthTrackingService? = null
private var healthTracker: HealthTracker? = null
private val ibiDataList = mutableListOf<Int>()
private val dateFormat = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault())
private val trackerEventListener = object : HealthTracker.TrackerEventListener {
override fun onDataReceived(dataPoints: List<DataPoint>) {
for (dataPoint in dataPoints) {
val validIbiList = getValidIbiList(dataPoint)
ibiDataList.addAll(validIbiList)
}
}
override fun onError(error: HealthTracker.TrackerError) {
Log.e("IBIWorker", "Error: $error")
}
override fun onFlushCompleted() {}
}
private fun isIBIValid(ibiStatus: Int, ibiValue: Int): Boolean {
return ibiStatus == 0 && ibiValue != 0
}
private fun getValidIbiList(dataPoint: DataPoint): List<Int> {
val ibiValues = dataPoint.getValue(ValueKey.HeartRateSet.IBI_LIST)
val ibiStatuses = dataPoint.getValue(ValueKey.HeartRateSet.IBI_STATUS_LIST)
return ibiValues.filterIndexed { index, value ->
isIBIValid(ibiStatuses[index], value)
}
}
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
return@withContext try {
val connectionDeferred = CompletableDeferred<Boolean>()
healthService = HealthTrackingService(object : ConnectionListener {
override fun onConnectionSuccess() {
connectionDeferredplete(true)
}
override fun onConnectionFailed(e: HealthTrackerException) {
Log.e("IBIWorker", "Connection Failed: $e")
connectionDeferredplete(false)
}
override fun onConnectionEnded() {}
}, context)
healthService?.connectService()
if (!connectionDeferred.await()) {
return@withContext Result.failure(workDataOf("error" to "Connection failed"))
}
startTracking()
delay(600000) // collect data for 10 min
stopTracking()
saveDataToFile()
Result.success()
} catch (e: Exception) {
Log.e("IBIWorker", "Error during work execution", e)
Result.failure(workDataOf("error" to e.message.toString()))
} finally {
healthService?.disconnectService()
healthService = null
}
}
private fun startTracking() {
try {
healthTracker = healthService?.getHealthTracker(HealthTrackerType.HEART_RATE_CONTINUOUS)
if (healthTracker == null) {
Log.e("IBIWorker", "Failed to create HealthTracker")
return
}
healthTracker?.setEventListener(trackerEventListener)
Log.d("IBIWorker", "Tracking started")
} catch (e: Exception) {
Log.e("IBIWorker", "Error starting tracking", e)
}
}
private fun stopTracking() {
healthTracker?.unsetEventListener()
}
private fun saveDataToFile() {
val fileName = "ibi_data_worker.txt"
val file = File(context.getExternalFilesDir(null), fileName)
try {
FileOutputStream(file, true).use { outputStream ->
val timestamp = dateFormat.format(Date())
outputStream.write("${timestamp}:\n".toByteArray())
ibiDataList.forEach { ibiValue ->
outputStream.write("${ibiValue},".toByteArray())
}
}
} catch (e: IOException) {
Log.e("IBIWorker", "Error saving to file", e)
} finally {
ibiDataList.clear()
}
}
}
And this is how I run it in the MainActivity
private fun requestPermissions() {
val permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissionGranted = permissions.all { it.value }
if (permissionGranted) {
scheduleIBIDataCollection()
}
else Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show()
}
permissionLauncher.launch(arrayOf(android.Manifest.permission.BODY_SENSORS))
}
private fun scheduleIBIDataCollection() {
val ibiWorkRequest = PeriodicWorkRequestBuilder<IBIDataCollectionWorker>(
repeatInterval = 60,
repeatIntervalTimeUnit = TimeUnit.MINUTES
).build()
WorkManager.getInstance(applicationContext).enqueueUniquePeriodicWork(
"ibi_data_collection",
ExistingPeriodicWorkPolicy.KEEP,
ibiWorkRequest
)
}
本文标签: wear osSamsung Health Sensor API Collecting IBI Data in Background on Galaxy WatchStack Overflow
版权声明:本文标题:wear os - Samsung Health Sensor API: Collecting IBI Data in Background on Galaxy Watch - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741283732a2370156.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论