Пассивные обновления данных подходят для приложений, которым необходимо отслеживать данные служб здравоохранения в фоновом режиме. Они предназначены для случаев, когда данные о здоровье и физической форме хранятся часами, днями и даже дольше. Если вам нужно хранить или обрабатывать данные о здоровье и физической форме, когда приложение не запущено, а пользователь не выполняет физические упражнения, используйте пассивный клиент служб здравоохранения.
Примеры использования пассивных данных см. в примерах «Пассивные данные» и «Пассивные цели» на GitHub.
Добавить зависимости
Чтобы добавить зависимость от Health Services, необходимо добавить репозиторий Google Maven в свой проект. Подробнее см. в репозитории Google Maven .
В файле build.gradle
уровня модуля добавьте следующую зависимость:
классный
dependencies { implementation "androidx.health:health-services-client:1.1.0-alpha05" }
Котлин
dependencies { implementation("androidx.health:health-services-client:1.1.0-alpha05") }
Проверить возможности
Прежде чем регистрироваться для получения обновлений данных, убедитесь, что устройство может предоставлять данные, необходимые вашему приложению. Проверка возможностей позволяет включать или отключать определённые функции, а также изменять пользовательский интерфейс приложения для компенсации недоступных функций.
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
. Требуйте разрешение Health Services, которое подтверждает, что только Health Services могут подключаться к службе:
<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
. При запуске устройства службам Health Services может потребоваться 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 отключен.
- Активные данные и упражнения
- Начните работу с плиткой
- Добавить заставку