Bu kılavuz, Health Connect 1.1.0-alpha11 sürümüyle uyumludur.
Health Connect, antrenman uygulamalarının antrenman planları yazmasına ve egzersiz uygulamalarının antrenman planlarını okumasına olanak tanımak için planlanmış egzersiz veri türünü sağlar. Kayıtlı egzersizler (antrenmanlar), kullanıcıların antrenman hedeflerine ulaşmalarına yardımcı olmak için kişiselleştirilmiş performans analizi için tekrar okunabilir.
Özellik kullanılabilirliği
Kullanıcının cihazının Health Connect'teki eğitim planlarını destekleyip desteklemediğini belirlemek için istemcide FEATURE_PLANNED_EXERCISE
'nin kullanılabilirliğini kontrol edin:
if (healthConnectClient
.features
.getFeatureStatus(
HealthConnectFeatures.FEATURE_PLANNED_EXERCISE
) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {
// Feature is available
} else {
// Feature isn't available
}
Daha fazla bilgi için Özellik kullanılabilirliğini kontrol etme başlıklı makaleyi inceleyin.
Gerekli izinler
Eğitim planlarına erişim aşağıdaki izinlerle korunur:
android.permission.health.READ_PLANNED_EXERCISE
android.permission.health.WRITE_PLANNED_EXERCISE
Aşağıdaki izinleri uygulamanız için Play Console'da ve uygulamanızın manifest dosyasında beyan edin:
<application>
<uses-permission
android:name="android.permission.health.READ_PLANNED_EXERCISE" />
<uses-permission
android:name="android.permission.health.WRITE_PLANNED_EXERCISE" />
...
</application>
Cihazlarınızda ve uygulamalarınızda kullanmak istediğiniz tüm uygun izinleri beyan etmek sizin sorumluluğunuzdadır. Ayrıca, her iznin kullanımdan önce kullanıcı tarafından verildiğini kontrol etmeniz gerekir.
Kullanıcıdan izin isteme
Uygulamanızın, istemci örneği oluşturduktan sonra kullanıcıdan izin istemesi gerekir. Kullanıcıların diledikleri zaman izin vermesine veya reddetmesine izin verilmelidir.
Bunun için gerekli veri türleri için bir dizi izin oluşturun. Öncelikle, gruptaki izinlerin Android manifest dosyanızda beyan edildiğinden emin olun.
// Create a set of permissions for required data types
val PERMISSIONS =
setOf(
HealthPermission.getReadPermission(HeartRateRecord::class),
HealthPermission.getWritePermission(HeartRateRecord::class),
HealthPermission.getReadPermission(PlannedExerciseSessionRecord::class),
HealthPermission.getWritePermission(PlannedExerciseSessionRecord::class),
HealthPermission.getReadPermission(ExerciseSessionRecord::class),
HealthPermission.getWritePermission(ExerciseSessionRecord::class)
)
Uygulamanıza gerekli izinlerin verilip verilmediğini görmek için getGrantedPermissions
'u kullanın. Aksi takdirde bu izinleri istemek için createRequestPermissionResultContract
değerini kullanın. Health Connect izinleri ekranı gösterilir.
// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()
val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
if (granted.containsAll(PERMISSIONS)) {
// Permissions successfully granted
} else {
// Lack of required permissions
}
}
suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
val granted = healthConnectClient.permissionController.getGrantedPermissions()
if (granted.containsAll(PERMISSIONS)) {
// Permissions already granted; proceed with inserting or reading data
} else {
requestPermissions.launch(PERMISSIONS)
}
}
Kullanıcılar izinleri istedikleri zaman verip iptal edebileceğinden, uygulamanızın izinleri düzenli olarak kontrol etmesi ve iznin kaybedildiği senaryoları ele alması gerekir.
İlgili izinler
Eğitim planları egzersiz oturumlarına bağlanır. Bu nedenle, kullanıcının Health Connect'in bu özelliğinden tam olarak yararlanabilmesi için bir eğitim planıyla ilgili her kayıt türünü kullanma izni vermesi gerekir.
Örneğin, bir antrenman planı bir dizi koşu sırasında kullanıcının kalp atış hızını ölçüyorsa egzersiz oturumunu yazmak ve sonuçları daha sonra değerlendirmek için geliştiricinin aşağıdaki izinleri belirtmesi ve kullanıcının bu izinleri vermesi gerekebilir:
android.permission.health.READ_EXERCISE
android.permission.health.READ_EXERCISE_ROUTE
android.permission.health.READ_HEART_RATE
android.permission.health.WRITE_EXERCISE
android.permission.health.WRITE_EXERCISE_ROUTE
android.permission.health.WRITE_HEART_RATE
Ancak genellikle antrenman planları oluşturan ve performansı planlara göre değerlendiren uygulama, antrenman planlarını kullanan ve gerçek egzersiz verilerini yazan uygulamayla aynı değildir. Uygulamanın türüne bağlı olarak, tüm okuma ve yazma izinlerine ihtiyaç duyulmayabilir. Örneğin, her uygulama türü için yalnızca şu izinlere ihtiyacınız olabilir:
Antrenman planı uygulaması | Egzersiz uygulaması |
---|---|
WRITE_PLANNED_EXERCISE |
READ_PLANNED_EXERCISE |
READ_EXERCISE |
WRITE_EXERCISE |
READ_EXERCISE_ROUTE |
WRITE_EXERCISE_ROUTE |
READ_HEART_RATE |
WRITE_HEART_RATE |
Planlanmış egzersiz oturumu kaydına dahil edilen bilgiler
- Oturum başlığı.
- Planlanmış egzersiz bloklarının listesi.
- Oturumun başlangıç ve bitiş zamanı.
- Egzersiz türü.
- Etkinlikle ilgili notlar.
- Meta veri
- Tamamlanmış egzersiz oturumu kimliği: Bu, planlanmış egzersiz oturumuyla ilgili bir egzersiz oturumu tamamlandıktan sonra otomatik olarak yazılır.
Planlanmış egzersiz bloğu kaydına dahil edilen bilgiler
Planlanmış bir egzersiz bloğu, farklı adım gruplarının tekrarını desteklemek için egzersiz adımlarının listesini içerir (örneğin, kol bükme, burpee ve mekik hareketlerini arka arkaya beş kez yapın).
- Bloğun açıklaması.
- Planlanan egzersiz adımlarının listesi.
- Tekrar sayısı.
Planlanmış egzersiz adımı kaydına dahil edilen bilgiler
- Adımın açıklaması.
- Egzersiz kategorisi.
- Egzersiz türü.
- Performans hedeflerinin listesi.
- Tamamlama hedefi.
Desteklenen toplama işlemleri
Bu veri türü için desteklenen toplama işlemi yoktur.
Örnek kullanım
Bir kullanıcının iki gün sonra 90 dakikalık bir koşu planladığını varsayalım. Bu koşuda, 90 ile 110 bpm arasında bir hedef nabızla gölün etrafında üç tur atılır.
- Kullanıcı, bir eğitim planı uygulamasında aşağıdakileri içeren planlanmış bir egzersiz oturumu tanımlar:
- Çalıştırmanın planlanan başlangıç ve bitiş zamanı
- Egzersiz türü (koşu)
- Tur sayısı (tekrar sayısı)
- Nabız için performans hedefi (90 ile 110 nabız/dk. arasında)
- Bu bilgiler, egzersiz blokları ve adımlar halinde gruplandırılır ve eğitim planı uygulaması tarafından
PlannedExerciseSessionRecord
olarak Health Connect'e yazılır. - Kullanıcı, planlanan oturumu gerçekleştirir (çalışır).
- Oturumla ilgili egzersiz verileri aşağıdaki durumlarda kaydedilir:
- Oturum sırasında giyilebilir cihazlar tarafından. Örneğin, nabız.
Bu veriler, etkinlik için kayıt türü olarak Health Connect'e yazılır. Bu durumda
HeartRateRecord
. - Oturumdan sonra kullanıcı tarafından manuel olarak. Örneğin, gerçek çalıştırmanın başlangıç ve bitiş zamanını belirtme. Bu veriler Health Connect'e
ExerciseSessionRecord
olarak yazılır.
- Oturum sırasında giyilebilir cihazlar tarafından. Örneğin, nabız.
Bu veriler, etkinlik için kayıt türü olarak Health Connect'e yazılır. Bu durumda
- Daha sonra eğitim planı uygulaması, planlanan egzersiz oturumunda kullanıcı tarafından belirlenen hedeflere göre gerçek performansı değerlendirmek için Health Connect'teki verileri okur.
Egzersizleri planlama ve hedefler belirleme
Kullanıcılar gelecekteki egzersizlerini planlayabilir ve hedefler belirleyebilir. Bunu Health Connect'e planlanmış egzersiz oturumu olarak yazın.
Kullanım örneği bölümünde açıklanan örnekte, kullanıcı iki gün sonra 90 dakikalık bir koşu planlamaktadır. Bu koşuda, hedef nabız 90 ile 110 arasında olacak şekilde gölün etrafında üç tur atılır.
Planlanmış egzersiz oturumlarını Health Connect'e kaydeden bir uygulamanın form işleyicisinde bu tür bir snippet bulunabilir. Bu, entegrasyonların besleme noktasında (ör. eğitim sunan bir hizmette) da bulunabilir.
// Ensure the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(PlannedExerciseSessionRecord::class))) {
// The user hasn't granted the app permission to write planned exercise session data.
return
}
val plannedDuration = Duration.ofMinutes(90)
val plannedStartDate = LocalDate.now().plusDays(2)
val plannedExerciseSessionRecord = PlannedExerciseSessionRecord(
startDate = plannedStartDate,
duration = plannedDuration,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
blocks = listOf(
PlannedExerciseBlock(
repetitions = 1, steps = listOf(
PlannedExerciseStep(
exerciseType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING,
exercisePhase = PlannedExerciseStep.EXERCISE_PHASE_ACTIVE,
completionGoal = ExerciseCompletionGoal.RepetitionsGoal(repetitions = 3),
performanceTargets = listOf(
ExercisePerformanceTarget.HeartRateTarget(
minHeartRate = 90.0, maxHeartRate = 110.0
)
)
),
), description = "Three laps around the lake"
)
),
title = "Run at lake",
notes = null,
metadata = Metadata.manualEntry(
device = Device(type = Device.Companion.TYPE_PHONE)
)
)
val insertedPlannedExerciseSessions =
healthConnectClient.insertRecords(listOf(plannedExerciseSessionRecord)).recordIdsList
val insertedPlannedExerciseSessionId = insertedPlannedExerciseSessions.first()
Egzersiz ve etkinlik verilerini günlüğe kaydetme
İki gün sonra kullanıcı gerçek egzersiz oturumunu kaydeder. Bunu Health Connect'e egzersiz seansı olarak yazın.
Bu örnekte, kullanıcının oturum süresi planlanan süreyle tam olarak eşleşti.
Aşağıdaki snippet, egzersiz oturumlarını Health Connect'e kaydeden bir uygulamanın form işleyicisinde bulunabilir. Ayrıca, egzersiz oturumlarını algılayıp kaydedebilen giyilebilir cihazların veri besleme ve dışa aktarma işleyicilerinde de bulunabilir.
Buradaki insertedPlannedExerciseSessionId
, önceki örnekten yeniden kullanılmıştır. Gerçek bir uygulamada kimlik, kullanıcının mevcut oturumların listesinden planlanmış bir egzersiz oturumu seçmesiyle belirlenir.
// Ensure the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(ExerciseSessionRecord::class))) {
// The user doesn't granted the app permission to write exercise session data.
return
}
val sessionDuration = Duration.ofMinutes(90)
val sessionEndTime = Instant.now()
val sessionStartTime = sessionEndTime.minus(sessionDuration)
val exerciseSessionRecord = ExerciseSessionRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
segments = listOf(
ExerciseSegment(
startTime = sessionStartTime,
endTime = sessionEndTime,
repetitions = 3,
segmentType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING
)
),
title = "Run at lake",
plannedExerciseSessionId = insertedPlannedExerciseSessionId,
metadata = Metadata.manualEntry(
device = Device(type = Device.Companion.TYPE_PHONE)
)
)
val insertedExerciseSessions =
healthConnectClient.insertRecords(listOf(exerciseSessionRecord))
Giyilebilir cihazlar, koşu sırasında nabzı da kaydeder. Aşağıdaki snippet, hedef aralıkta kayıt oluşturmak için kullanılabilir.
Gerçek bir uygulamada bu snippet'in birincil parçaları, giyilebilir cihazdan gelen bir ileti için işleyicide bulunabilir. Bu işleyici, ölçüm toplandıktan sonra Health Connect'e yazar.
// Ensure the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(HeartRateRecord::class))) {
// The user doesn't granted the app permission to write heart rate record data.
return
}
val samples = mutableListOf<HeartRateRecord.Sample>()
var currentTime = sessionStartTime
while (currentTime.isBefore(sessionEndTime)) {
val bpm = Random.nextInt(21) + 90
val heartRateRecord = HeartRateRecord.Sample(
time = currentTime,
beatsPerMinute = bpm.toLong(),
)
samples.add(heartRateRecord)
currentTime = currentTime.plusSeconds(180)
}
val heartRateRecord = HeartRateRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
samples = samples,
metadata = Metadata.autoRecorded(
device = Device(type = Device.Companion.TYPE_WATCH)
)
)
val insertedHeartRateRecords = healthConnectClient.insertRecords(listOf(heartRateRecord))
Performans hedeflerini değerlendirme
Kullanıcının antrenmanından bir gün sonra, kaydedilen antrenmanı alabilir, planlanmış antrenman hedeflerini kontrol edebilir ve belirlenen hedeflerin karşılanıp karşılanmadığını belirlemek için ek veri türlerini değerlendirebilirsiniz.
Bu tür bir snippet, performans hedeflerini değerlendirmek için yapılan düzenli bir işte veya bir uygulamada alıştırma listesi yüklenirken ve performans hedefleri hakkında bildirim gösterilirken bulunabilir.
// Ensure the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.containsAll(
listOf(
HealthPermission.getReadPermission(ExerciseSessionRecord::class),
HealthPermission.getReadPermission(PlannedExerciseSessionRecord::class),
HealthPermission.getReadPermission(HeartRateRecord::class)
)
)
) {
// The user doesn't granted the app permission to read exercise session record data.
return
}
val searchDuration = Duration.ofDays(1)
val searchEndTime = Instant.now()
val searchStartTime = searchEndTime.minus(searchDuration)
val response = healthConnectClient.readRecords(
ReadRecordsRequest<ExerciseSessionRecord>(
timeRangeFilter = TimeRangeFilter.between(searchStartTime, searchEndTime)
)
)
for (exerciseRecord in response.records) {
val plannedExerciseRecordId = exerciseRecord.plannedExerciseSessionId
val plannedExerciseRecord =
if (plannedExerciseRecordId == null) null else healthConnectClient.readRecord(
PlannedExerciseSessionRecord::class, plannedExerciseRecordId
).record
if (plannedExerciseRecord != null) {
val aggregateRequest = AggregateRequest(
metrics = setOf(HeartRateRecord.BPM_AVG),
timeRangeFilter = TimeRangeFilter.between(
exerciseRecord.startTime, exerciseRecord.endTime
),
)
val aggregationResult = healthConnectClient.aggregate(aggregateRequest)
val maxBpm = aggregationResult[HeartRateRecord.BPM_MAX]
val minBpm = aggregationResult[HeartRateRecord.BPM_MIN]
if (maxBpm != null && minBpm != null) {
plannedExerciseRecord.blocks.forEach { block ->
block.steps.forEach { step ->
step.performanceTargets.forEach { target ->
when (target) {
is ExercisePerformanceTarget.HeartRateTarget -> {
val minTarget = target.minHeartRate
val maxTarget = target.maxHeartRate
if(
minBpm >= minTarget && maxBpm <= maxTarget
) {
// Success!
}
}
// Handle more target types
}
}
}
}
}
}
}
}