被动数据更新适用于需要在后台监控健康服务数据的应用。它们适用于持续数小时、数天甚至更长时间的用例。如果您需要在应用未运行,且用户未明确参与某项运动时存储或处理健康数据,请使用健康服务的被动客户端。
如需查看被动数据使用示例,请参阅 GitHub 上的被动数据和被动目标示例。
添加依赖项
如需添加健康服务的依赖项,您必须将 Google Maven 制品库添加到项目中。如需了解相关信息,请参阅 Google 的 Maven 制品库。
在您的模块级 build.gradle 文件中,添加以下依赖项:
Groovy
dependencies {
implementation "androidx.health:health-services-client:1.0.0-beta02"
}
Kotlin
dependencies {
implementation("androidx.health:health-services-client:1.0.0-beta02")
}
检查功能
在注册数据更新之前,请检查设备是否可以提供您的应用所需的数据类型。检查功能,您便可以启用或停用某些功能,或修改应用的界面以弥补不可用的功能。
val healthClient = HealthServices.getClient(this /*context*/)
val passiveMonitoringClient = healthClient.passiveMonitoringClient
lifecycleScope.launchWhenCreated {
val capabilities = passiveMonitoringClient.capabilities.await()
// Supported types for passive data collection
supportsHeartRate =
DataType.HEART_RATE_BPM in capabilities.supportedDataTypesPassiveMonitoring
// Supported types for PassiveGoals
supportsStepsGoal =
DataType.STEPS_DAILY in capabilities.supportedDataTypesPassiveGoals
}
注册被动数据
您可以通过服务和/或回调接收被动数据。借助服务,即使您的应用的任何部分均未在前台显示,您的应用也能在后台接收数据。当您在后台接收数据时,这些数据会批量传送。回调能够以略快一些的速度接收数据,但仅适用于应用正在运行且回调通知成功的情况。
无论您使用哪种方法,都需要先创建一个 PassiveListenerConfig 来确定要接收哪些数据类型,如以下示例所示:
val passiveListenerConfig = PassiveListenerConfig.builder()
.setDataTypes(setOf(DataType.HEART_RATE_BPM))
.build()
如需使用回调接收数据,请定义并注册回调,如以下示例所示:
val passiveListenerCallback: PassiveListenerCallback = object : PassiveListenerCallback {
override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
// TODO: Do something with dataPoints
}
}
passiveMonitoringClient.setPassiveListenerCallback(
passiveListenerConfig,
passiveListenerCallback
)
// To remove the listener
passiveMonitoringClient.clearPassiveListenerCallbackAsync()
使用服务所需的操作与使用回调类似,但此时不应创建从 PassiveListenerCallback 衍生的类,而要从 PassiveListenerService 衍生,如以下示例所示:
class PassiveDataService : PassiveListenerService() {
override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
// TODO: Do something with dataPoints
}
}
passiveMonitoringClient.setPassiveListenerServiceAsync(
PassiveDataService::class.java,
passiveListenerConfig
)
接下来,在您的 AndroidManifest.xml 文件中声明相应服务。您需要具备健康服务权限,以确保只有健康服务才能绑定到该服务:
<service android:name=".PassiveDataService"
android:permission="com.google.android.wearable.healthservices.permission.PASSIVE_DATA_BINDING"
android:exported="true" />
解译时间
从健康服务收到的数据是批量发送的,因此在同一批数据中,您可能会收到不同类型的数据点,也可能会收到同一类型的多个数据点。请使用这些对象中包含的时间戳(而不是应用收到它们的时间)来确定事件的正确顺序。
通过首先计算启动时间戳获取每个 DataPoint 的时间戳,如以下示例所示:
val bootInstant =
Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())
然后,可以将此值传递给 getStartInstant() 或 getEndInstant()。
启动后恢复注册
被动数据注册会在重启后被清除。如需在设备重启后接收数据,请使用监听 ACTION_BOOT_COMPLETED 系统广播的 BroadcastReceiver 重新创建注册。
在接收器中,请勿尝试直接恢复注册。相反,请将此功能委托给 WorkManager 工作器。设备启动时,健康服务可能需要 10 秒或更长的时间来确认被动数据注册请求,并且此过程可能会超出 BroadcastReceiver 的允许执行时间。相比之下,WorkManager 工作器的执行时间上限为 10 分钟。
BroadcastReceiver 可能如以下代码段所示:
class StartupReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action != Intent.ACTION_BOOT_COMPLETED) return
// TODO: Check permissions first
WorkManager.getInstance(context).enqueue(
OneTimeWorkRequestBuilder<RegisterForPassiveDataWorker>().build()
)
}
}
class RegisterForPassiveDataWorker(
private val appContext: Context,
workerParams: WorkerParameters
) : Worker(appContext, workerParams) {
override fun doWork(): Result {
runBlocking {
HealthServices.getClient(appContext)
.passiveMonitoringClient
.setPassiveListenerCallback(...)
}
return Result.success()
}
}
如需安排系统在设备启动时执行此代码,请对 AndroidManifest.xml 文件进行两项更改。
首先,将以下权限添加为 的子项:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
然后,将以下接收器 intent 过滤器添加为 的子项:
<receiver
android:name=".StartupReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
activity 状态
被动客户端还可以提供有关用户状态的概要信息,例如用户是否处于睡眠状态。如需接收这些更新,请按以下步骤操作:
请求 ACTIVITY_RECOGNITION 权限。
在 PassiveListenerConfig 构建器中调用 setShouldUserActivityInfoBeRequested(true)。
替换回调或服务中的 onUserActivityInfoReceived() 方法,并使用返回的 UserActivityInfo,如以下示例所示:
override fun onUserActivityInfoReceived(info: UserActivityInfo) {
val stateChangeTime: Instant = info.stateChangeTime // may be in the past!
val userActivityState: UserActivityState = info.userActivityState
if (userActivityState == UserActivityState.USER_ACTIVITY_ASLEEP) {
// ...
}
}
被动目标
您可以配置一个被动客户端,以便在被动目标达成(例如用户每天走完 10,000 步)时通知应用。
为此,请创建目标,如以下示例所示:
val dailyStepsGoal by lazy {
val condition = DataTypeCondition(
dataType = DataType.STEPS_DAILY,
threshold = 10_000, // Trigger every 10000 steps
comparisonType = ComparisonType.GREATER_THAN_OR_EQUAL
)
PassiveGoal(condition)
}
将此目标添加到 PassiveListenerConfig,如以下示例所示:
val passiveListenerConfig = PassiveListenerConfig.builder()
.setDailyGoals(setOf(dailyStepsGoal))
.build()
替换回调或服务中的 onGoalCompleted() 方法,并使用返回的 PassiveGoal,如以下示例所示:
override fun onGoalCompleted(goal: PassiveGoal) {
when (goal.dataTypeCondition.dataType) {
DataType.STEPS_DAILY -> {
// ...
}
}
}
目前没有任何推荐文档页面。
请尝试登录您的 Google 账号。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2023-08-03。