Health Connect: Gate DistanceSyncer with supportsActivityDistance flag

Add supportsActivityDistance coordinator capability flag following the
supportsActiveCalories pattern. When true, DistanceSyncer syncs all
per-minute distance and RecordedWorkoutSyncer skips DistanceRecords.

Enabled for Garmin (watch + bike), Xiaomi, and Huawei. Other devices
with distance fields (CMF, Colmi, H+, etc.) left at default false
until per-minute data quality is verified.
This commit is contained in:
Gideon Zenz
2026-04-07 10:30:40 +02:00
parent da3f21aafb
commit 4d8ef91b13
8 changed files with 38 additions and 2 deletions
@@ -682,6 +682,11 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
return false;
}
@Override
public boolean supportsActivityDistance(@NonNull GBDevice device) {
return false;
}
@Override
public boolean supportsTrainingLoad(@NonNull GBDevice device) {
return false;
@@ -292,6 +292,7 @@ public interface DeviceCoordinator {
boolean supportsSpeedzones(@NonNull GBDevice device);
boolean supportsCharts(@NonNull GBDevice device);
boolean supportsActiveCalories(@NonNull GBDevice device);
boolean supportsActivityDistance(@NonNull GBDevice device);
boolean supportsTrainingLoad(@NonNull GBDevice device);
boolean supportsGlucoseMeasurement(@NonNull GBDevice device);
@@ -27,6 +27,11 @@ public abstract class GarminBikeComputerCoordinator extends GarminCoordinator {
return true;
}
@Override
public boolean supportsActivityDistance(@NonNull GBDevice device) {
return true;
}
@Override
public boolean supportsVO2Max(@NonNull GBDevice device) {
return true;
@@ -102,6 +102,11 @@ public abstract class GarminWatchCoordinator extends GarminCoordinator {
return true;
}
@Override
public boolean supportsActivityDistance(@NonNull GBDevice device) {
return true;
}
@Override
public int[] getStressRanges() {
// 1-25 = relaxed
@@ -304,6 +304,11 @@ public abstract class HuaweiCoordinator extends AbstractDeviceCoordinator {
return true;
}
@Override
public boolean supportsActivityDistance(@NonNull final GBDevice device) {
return true;
}
@Override
public boolean supportsActivityTracking(@NonNull final GBDevice device) {
return true;
@@ -326,6 +326,11 @@ public abstract class XiaomiCoordinator extends AbstractBLEDeviceCoordinator {
return true;
}
@Override
public boolean supportsActivityDistance(@NonNull GBDevice device) {
return true;
}
@Override
public boolean supportsSleepRespiratoryRate(@NonNull GBDevice device) {
// TODO it does
@@ -602,6 +602,12 @@ class HealthConnectUtils {
currentSliceStartTs, currentSliceEndTs, grantedPermissions, activityBasedSamples
))
}
if (gbDevice.deviceCoordinator.supportsActivityDistance(gbDevice)) {
sliceStats.add(DistanceSyncer.sync(
healthConnectClient, gbDevice, metadata, offset,
currentSliceStartTs, currentSliceEndTs, grantedPermissions, activityBasedSamples
))
}
}
}
HealthConnectPermissionManager.HealthConnectDataType.SLEEP -> {
@@ -351,7 +351,9 @@ internal object RecordedWorkoutSyncer {
val summaryData = parseSummaryData(workout.summaryData)
if (summaryData != null) {
addDistanceRecord(summaryData, workoutStartInstant, workoutEndInstant, startOffset, endOffset, metadata, grantedPermissions, recordsToInsert, deviceName)
if (!device.deviceCoordinator.supportsActivityDistance(device)) {
addDistanceRecord(summaryData, workoutStartInstant, workoutEndInstant, startOffset, endOffset, metadata, grantedPermissions, recordsToInsert, deviceName)
}
if (!device.deviceCoordinator.supportsActiveCalories(device)) {
addCaloriesRecords(summaryData, workoutStartInstant, workoutEndInstant, startOffset, endOffset, metadata, grantedPermissions, recordsToInsert, deviceName)
}
@@ -389,7 +391,9 @@ internal object RecordedWorkoutSyncer {
val summaryData = parseSummaryData(workout.summaryData)
if (summaryData != null) {
addDistanceRecord(summaryData, workoutStartInstant, workoutEndInstant, startOffset, endOffset, metadata, grantedPermissions, recordsToInsert, deviceName)
if (!gbDevice.deviceCoordinator.supportsActivityDistance(gbDevice)) {
addDistanceRecord(summaryData, workoutStartInstant, workoutEndInstant, startOffset, endOffset, metadata, grantedPermissions, recordsToInsert, deviceName)
}
addSpeedRecord(summaryData, workoutStartInstant, workoutEndInstant, startOffset, endOffset, metadata, grantedPermissions, recordsToInsert, deviceName)
if (!gbDevice.deviceCoordinator.supportsActiveCalories(gbDevice)) {
addCaloriesRecords(summaryData, workoutStartInstant, workoutEndInstant, startOffset, endOffset, metadata, grantedPermissions, recordsToInsert, deviceName)