Verileri arka planda izleme

Pasif veri güncellemeleri, arka planda Sağlık Hizmetleri verilerini izlemesi gereken uygulamalar için uygundur. Saatler, günler veya daha uzun süreler boyunca devam eden kullanım alanları için tasarlanmıştır. Uygulamanız çalışmıyorken ve kullanıcı açıkça egzersiz yapmıyorken sağlık ve fitness verilerini depolamanız veya işlemeniz gerekiyorsa Health Service'in pasif istemcisini kullanın.

Pasif veri kullanımına ilişkin örnekler için GitHub'daki Pasif Veriler ve Pasif Hedefler örneklerine bakın.

Bağımlılık ekleme

Sağlık Hizmetleri'ne bağımlılık eklemek için projenize Google Maven deposunu eklemeniz gerekir. Daha fazla bilgi için Google'ın Maven deposuna bakın.

Modül düzeyindeki build.gradle dosyanıza aşağıdaki bağımlılığı ekleyin:

Groovy

dependencies {
    implementation "androidx.health:health-services-client:1.1.0-alpha05"
}

Kotlin

dependencies {
    implementation("androidx.health:health-services-client:1.1.0-alpha05")
}

Özellikleri kontrol etme

Veri güncellemelerine kaydolmadan önce cihazın, uygulamanızın ihtiyaç duyduğu veri türünü sağlayabildiğinden emin olun. Kontrol etme özellikleri, belirli özellikleri etkinleştirmenize veya devre dışı bırakmanıza ya da kullanılamayan özellikleri telafi etmek için uygulamanızın kullanıcı arayüzünü değiştirmenize olanak tanır.

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
}

Pasif veriler için kaydolma

Bir hizmet, geri arama veya her ikisi aracılığıyla pasif veriler alabilirsiniz. Bir hizmet, uygulamanızın hiçbir bölümü ön planda görünmüyorken uygulamanızın arka planda veri almasına olanak tanır. Arka planda veri aldığınızda veriler toplu olarak teslim edilir. Geri çağırma, verileri biraz daha hızlı bir şekilde alır ancak yalnızca uygulama çalışırken ve geri çağırma başarılı bir şekilde bildirilirken.

Hangi yöntemi kullanırsanız kullanın, önce aşağıdaki örnekte gösterildiği gibi hangi veri türlerinin alınacağını belirleyen bir PassiveListenerConfig oluşturun:

val passiveListenerConfig = PassiveListenerConfig.builder()
    .setDataTypes(setOf(DataType.HEART_RATE_BPM))
    .build()

Geri çağırma işlevini kullanarak veri almak için geri çağırma işlevini tanımlayıp kaydedin. Aşağıdaki örnekte bu işlem gösterilmektedir:

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()

Hizmet kullanmak da benzerdir ancak PassiveListenerCallback öğesinden türetilmiş bir sınıf oluşturmak yerine aşağıdaki örnekte gösterildiği gibi PassiveListenerService öğesinden türetin:

class PassiveDataService : PassiveListenerService() {
    override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
        // TODO: Do something with dataPoints
    }
}

passiveMonitoringClient.setPassiveListenerServiceAsync(
    PassiveDataService::class.java,
    passiveListenerConfig
)

Ardından, hizmeti AndroidManifest.xml dosyanızda bildirin. Yalnızca Sağlık Hizmetleri'nin hizmete bağlanabildiğini doğrulayan bir Sağlık Hizmetleri izni gerektirir:

<service android:name=".PassiveDataService"
    android:permission="com.google.android.wearable.healthservices.permission.PASSIVE_DATA_BINDING"
    android:exported="true" />

Yorumlama süresi

Sağlık Hizmetleri'nden aldığınız veriler toplu olarak gönderilir. Bu nedenle, aynı toplu işlemde farklı türlerdeki veri noktalarını veya aynı türdeki birden fazla veri noktasını alabilirsiniz. Etkinliklerin doğru sırasını belirlemek için bu nesnelerde yer alan zaman damgalarını kullanın. Etkinliklerin uygulamanız tarafından alındığı zamanı kullanmayın.

Öncelikle aşağıdaki örnekte gösterildiği gibi başlatma zaman damgasını hesaplayarak her DataPoint için zaman damgaları alın:

val bootInstant =
    Instant.ofEpochMilli(System.currentTimeMillis() - SystemClock.elapsedRealtime())

Bu değer daha sonra getStartInstant() veya getEndInstant()'a iletilebilir.

Başlatma işleminden sonra kayıtları geri yükleme

Pasif veri kayıtları, yeniden başlatma işlemleri sırasında kalıcı olmaz. Bir cihaz yeniden başlatıldıktan sonra veri almak için ACTION_BOOT_COMPLETED sistem yayınını dinleyen bir BroadcastReceiver kullanarak kayıtlarınızı yeniden oluşturun.

Alıcıda, kayıtları doğrudan geri yüklemeye çalışmayın. Bunun yerine, bu işlevi bir WorkManager çalışana devredin. Cihaz başlatılırken Sağlık Hizmetleri'nin pasif veri kaydı isteğini onaylaması 10 saniye veya daha uzun sürebilir. Bu süre, BroadcastReceiver için izin verilen yürütme süresini aşabilir. Buna karşılık, WorkManager işçilerinin 10 dakikalık bir yürütme sınırı vardır.

Aşağıdaki snippet'te BroadcastReceiver simgesinin nasıl görünebileceği gösterilmektedir:

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()
   }
}

Sistemin bu kodu cihaz başlatıldığında yürütmesini sağlamak için AndroidManifest.xml dosyasında iki değişiklik yapın.

Öncelikle aşağıdaki izni <manifest> öğesinin alt öğesi olarak ekleyin:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

İkinci olarak, aşağıdaki alıcı intent filtresini <application> öğesinin alt öğesi olarak ekleyin:

<receiver
    android:name=".StartupReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

Etkinlik eyaleti

Pasif istemci, kullanıcı durumu hakkında üst düzey bilgiler de sağlayabilir. Örneğin, kullanıcının uyuyup uyumadığı gibi. Bu güncellemeleri almak için aşağıdaki adımları uygulayın:

  1. ACTIVITY_RECOGNITION iznini isteyin.
  2. PassiveListenerConfig oluşturucusunda setShouldUserActivityInfoBeRequested(true) işlevini çağırın.

Geri çağırma işlevinizde veya hizmetinizde onUserActivityInfoReceived() yöntemini geçersiz kılın ve döndürülen UserActivityInfo değerini aşağıdaki örnekte gösterildiği gibi kullanın:

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) {
        // ...
    }
}

Pasif hedefler

Pasif bir istemciyi, pasif hedeflere (ör. kullanıcının bir günde 10.000 adım atması) ulaşıldığında uygulamayı bilgilendirecek şekilde yapılandırabilirsiniz.

Bunu yapmak için aşağıdaki örnekte gösterildiği gibi bir hedef oluşturun:

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)
}

Bu hedefi, aşağıdaki örnekte gösterildiği gibi PassiveListenerConfig öğenize ekleyin:

val passiveListenerConfig = PassiveListenerConfig.builder()
    .setDailyGoals(setOf(dailyStepsGoal))
    .build()

Geri çağırma işlevinizde veya hizmetinizde onGoalCompleted() yöntemini geçersiz kılın ve döndürülen PassiveGoal değerini aşağıdaki örnekte gösterildiği gibi kullanın:

override fun onGoalCompleted(goal: PassiveGoal) {
    when (goal.dataTypeCondition.dataType) {
        DataType.STEPS_DAILY -> {
            // ...
        }
    }
}