Пассивные обновления данных подходят для приложений, которым необходимо отслеживать данные сервисов наблюдения за здоровьем в фоновом режиме. Они предназначены для сценариев использования, которые охватывают часы, дни или даже больше. Если вам нужно хранить или обрабатывать данные о здоровье и физической активности, когда приложение не запущено и пользователь не занимается спортом, используйте пассивный клиент сервисов наблюдения за здоровьем.
Примеры использования пассивных данных можно найти в разделах Пассивные данные и Пассивные цели на GitHub.
Добавьте зависимости
Чтобы добавить зависимость от сервисов наблюдения за здоровьем, добавьте в проект репозиторий Google Maven. Дополнительную информацию можно найти в статье Репозиторий Maven от Google.
В файле build.gradle на уровне модуля добавьте следующую зависимость:
классный
dependencies { implementation "androidx.health:health-services-client:1.1.0" }
Котлин
dependencies { implementation("androidx.health:health-services-client:1.1.0") }
Проверить возможности
Прежде чем регистрироваться для получения обновлений данных, убедитесь, что устройство может предоставлять тип данных, необходимых вашему приложению. Проверка возможностей позволяет включать или отключать определенные функции или изменять пользовательский интерфейс приложения, чтобы компенсировать недоступные функции.
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().
Восстановление регистраций после загрузки
Регистрации пассивных данных не сохраняются после перезагрузки. Чтобы получать данные после перезапуска устройства, повторно создайте регистрации с помощью BroadcastReceiver, который прослушивает системную широковещательную рассылку ACTION_BOOT_COMPLETED.
Не пытайтесь восстановить регистрации напрямую в получателе. Вместо этого делегируйте эту функцию исполнителю 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.
Сначала добавьте следующее разрешение в качестве дочернего для элемента <manifest>:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Затем добавьте следующий фильтр интентов получателя в качестве дочернего элемента <application>:
<receiver
android:name=".StartupReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Статус активности
Пассивный клиент также может предоставлять общую информацию о состоянии пользователя, например о том, спит ли он. Чтобы получать эти обновления, выполните следующие действия:
- Запросите разрешение
ACTIVITY_RECOGNITION. - Вызовите
setShouldUserActivityInfoBeRequested(true)в конструктореPassiveListenerConfig.
Переопределите метод 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 -> {
// ...
}
}
}
Рекомендуем
- Примечание. Текст ссылки показывается, когда JavaScript отключен.
- Активные данные и упражнения
- Как начать работу с карточками
- Как добавить заставку