在移动设备上使用传感器管理器测量步数

365 office login email 📅 2025-08-05 02:58:22 👤 admin 👀 7455 ❤️ 264
在移动设备上使用传感器管理器测量步数

注意 :本指南使用 SensorManager 检索步数数据。我们建议

在移动设备上使用 Recording API

以省电的方式记录步数。

使用传感器管理器在移动应用中填充步数数据,如下所述

指南。如需详细了解如何设计和管理锻炼应用界面,

参阅

构建基本健身应用。

使用入门

要开始测量基本计步器的步数,请开始使用

您需要将依赖项添加到您的应用模块

build.gradle 文件。确保使用最新版本的依赖项。

此外,当您将应用的支持扩展到其他类型的设备(例如 Wear OS)时,

添加这些外形规格所需的依赖项

以下是一些界面依赖项的示例。如需查看完整列表

请参阅此界面元素指南。

implementation(platform("androidx.compose:compose-bom:2023.10.01"))

implementation("androidx.activity:activity-compose")

implementation("androidx.compose.foundation:foundation")

implementation("androidx.compose.material:material")

获取计步器传感器

在用户授予必要的运动状态识别权限后,

您可以访问计步器传感器:

从 getSystemService() 获取 SensorManager 对象。

从 SensorManager 获取计步器传感器:

private val sensorManager by lazy {

getSystemService(Context.SENSOR_SERVICE) as SensorManager }

private val sensor: Sensor? by lazy {

sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) }

部分设备没有计步器传感器。您应检查传感器

如果设备没有该设备,就会显示一条错误消息:

if (sensor == null) {

Text(text = "Step counter sensor is not present on this device")

}

创建前台服务

在基本的健身应用中,您可能会有一个按钮

接收来自用户的开始和停止事件以跟踪步数。

请谨记与传感器相关的最佳实践。

具体而言,计步器传感器在测量步数时,

监听器。通过将传感器注册与前台相关联

服务,只要需要,传感器就会注册,传感器可以

应用未在前台运行时保持注册状态。

使用以下代码段在 onPause() 方法中取消注册传感器

您的前台服务:

override fun onPause() {

super.onPause()

sensorManager.unregisterListener(this)

}

分析事件数据

如需访问传感器数据,请实现 SensorEventListener 接口。注意事项

您应该将传感器注册与前台服务的

生命周期,在服务暂停或结束时取消注册传感器。通过

以下代码段展示了如何实现 SensorEventListener 接口

对于 Sensor.TYPE_STEP_COUNTER:

private const val TAG = "STEP_COUNT_LISTENER"

context(Context)

class StepCounter {

private val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

private val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)

suspend fun steps() = suspendCancellableCoroutine { continuation ->

Log.d(TAG, "Registering sensor listener... ")

val listener: SensorEventListener by lazy {

object : SensorEventListener {

override fun onSensorChanged(event: SensorEvent?) {

if (event == null) return

val stepsSinceLastReboot = event.values[0].toLong()

Log.d(TAG, "Steps since last reboot: $stepsSinceLastReboot")

if (continuation.isActive) {

continuation.resume(stepsSinceLastReboot)

}

}

override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {

Log.d(TAG, "Accuracy changed to: $accuracy")

}

}

}

val supportedAndEnabled = sensorManager.registerListener(listener,

sensor, SensorManager.SENSOR_DELAY_UI)

Log.d(TAG, "Sensor listener registered: $supportedAndEnabled")

}

}

为传感器事件创建数据库

您的应用可能会显示一个屏幕,供用户查看其在一段时间内的步数。

如需在您的应用中提供此功能,请使用 Room 持久性库。

以下代码段会创建一个包含一组步数的表格

测量值,以及您的应用访问每个测量值的时间:

@Entity(tableName = "steps")

data class StepCount(

@ColumnInfo(name = "steps") val steps: Long,

@ColumnInfo(name = "created_at") val createdAt: String,

)

创建数据访问对象 (DAO)

读写数据:

@Dao

interface StepsDao {

@Query("SELECT * FROM steps")

suspend fun getAll(): List

@Query("SELECT * FROM steps WHERE created_at >= date(:startDateTime) " +

"AND created_at < date(:startDateTime, '+1 day')")

suspend fun loadAllStepsFromToday(startDateTime: String): Array

@Insert

suspend fun insertAll(vararg steps: StepCount)

@Delete

suspend fun delete(steps: StepCount)

}

如需实例化 DAO,请创建一个 RoomDatabase 对象:

@Database(entities = [StepCount::class], version = 1)

abstract class AppDatabase : RoomDatabase() {

abstract fun stepsDao(): StepsDao

}

将传感器数据存储在数据库中

ViewModel 使用新的 StepCounter 类,因此您可以尽快存储步骤

您可以这样理解:

viewModelScope.launch {

val stepsFromLastBoot = stepCounter.steps()

repository.storeSteps(stepsFromLastBoot)

}

repository 类如下所示:

class Repository(

private val stepsDao: StepsDao,

) {

suspend fun storeSteps(stepsSinceLastReboot: Long) = withContext(Dispatchers.IO) {

val stepCount = StepCount(

steps = stepsSinceLastReboot,

createdAt = Instant.now().toString()

)

Log.d(TAG, "Storing steps: $stepCount")

stepsDao.insertAll(stepCount)

}

suspend fun loadTodaySteps(): Long = withContext(Dispatchers.IO) {

printTheWholeStepsTable() // DEBUG

val todayAtMidnight = (LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT).toString())

val todayDataPoints = stepsDao.loadAllStepsFromToday(startDateTime = todayAtMidnight)

when {

todayDataPoints.isEmpty() -> 0

else -> {

val firstDataPointOfTheDay = todayDataPoints.first()

val latestDataPointSoFar = todayDataPoints.last()

val todaySteps = latestDataPointSoFar.steps - firstDataPointOfTheDay.steps

Log.d(TAG, "Today Steps: $todaySteps")

todaySteps

}

}

}

}

定期检索传感器数据

如果您使用前台服务,则无需配置 WorkManager

因为在应用主动跟踪用户的步数时

更新后的总步数应该会显示在应用中。

不过,如果您希望批量记录步数,可以使用 WorkManager 来

按特定的时间间隔测量步数,如每 15 分钟一次。

WorkManager 是执行背景的组件

以确保执行有保证执行如需了解详情,请参阅 WorkManager Codelab。

如需配置 Worker 对象以检索数据,请替换 doWork()

方法,如以下代码段所示:

private const val TAG = " StepCounterWorker"

@HiltWorker

class StepCounterWorker @AssistedInject constructor(

@Assisted appContext: Context,

@Assisted workerParams: WorkerParameters,

val repository: Repository,

val stepCounter: StepCounter

) : CoroutineWorker(appContext, workerParams) {

override suspend fun doWork(): Result {

Log.d(TAG, "Starting worker...")

val stepsSinceLastReboot = stepCounter.steps().first()

if (stepsSinceLastReboot == 0L) return Result.success()

Log.d(TAG, "Received steps from step sensor: $stepsSinceLastReboot")

repository.storeSteps(stepsSinceLastReboot)

Log.d(TAG, "Stopping worker...")

return Result.success()

}

}

如需将 WorkManager 设置为每 15 分钟存储一次当前步数,请执行以下操作:

以下:

扩展 Application 类以实现 Configuration.Provider

界面。

在 onCreate() 方法中,将 PeriodicWorkRequestBuilder 加入队列。

此过程显示在以下代码段中:

@HiltAndroidApp

@RequiresApi(Build.VERSION_CODES.S)

internal class PulseApplication : Application(), Configuration.Provider {

@Inject

lateinit var workerFactory: HiltWorkerFactory

override fun onCreate() {

super.onCreate()

val myWork = PeriodicWorkRequestBuilder(

15, TimeUnit.MINUTES).build()

WorkManager.getInstance(this)

.enqueueUniquePeriodicWork("MyUniqueWorkName",

ExistingPeriodicWorkPolicy.UPDATE, myWork)

}

override val workManagerConfiguration: Configuration

get() = Configuration.Builder()

.setWorkerFactory(workerFactory)

.setMinimumLoggingLevel(android.util.Log.DEBUG)

.build()

}

初始化控制对应用步骤的访问权限的 content provider

计数器数据库,请将以下元素添加到

应用的清单文件:

android:name="androidx.startup.InitializationProvider"

android:authorities="${applicationId}.androidx-startup"

tools:node="remove" />

🍵 相关养生推荐

遠(远)
bt365全程担保

遠(远)

📅 07-10 👀 6479
什么是WCDMA,WCDMA的知识介绍
bt365全程担保

什么是WCDMA,WCDMA的知识介绍

📅 07-05 👀 4567
免費在線更改照片背景顏色
bt365全程担保

免費在線更改照片背景顏色

📅 07-02 👀 2221
中甲一共多少轮 中甲总共几轮
365 office login email

中甲一共多少轮 中甲总共几轮

📅 07-27 👀 6472