Android Health Connect Backfill

Data is stored exclusively on the device (running Android). Backfilling is possible from the moment application user grants permissions and is limited by:
  • What data the user has on their device
  • What permissions your app has been granted (read access for specific data types)
  • User’s health app settings or deletions
  • Your retention policy settings
  • 30 days period predating permission grant

Permission Timing and Historical Data Access

Permission request timing is not relevant, meaning that if application user decides to approve permission a week later by going directly into health connect settings menu, you will be able to access data 23 days prior to installing the app. For apps targeting Android API level 34 (Android 14) and higher, Google has introduced PERMISSION_READ_HEALTH_DATA_HISTORY which allows access to health data recorded before the app was installed, extending beyond the standard 30-day limitation.

Manual Data Extraction Required

Because Google doesn’t offer any other communication except health connect client, you must query needed data manually in order to backfill it. We recommend keeping this process asynchronous for the best user experience and segmented to ensure best performance. Before data is extracted it won’t be available to your backend over API calls. Enabling background data delivery also won’t perform the backfill as it’s designed for new data events.
Ensure your app handles data synchronization efficiently to minimize battery and resource usage. Implement background processing where appropriate to avoid impacting app performance.

Implementation

import java.time.LocalDate
import java.time.ZoneId
import java.time.Instant

// Example: Backfill last 7 days of steps data
val today = LocalDate.now()

for (dayOffset in 0 until 7) {
    val startDate = today.minusDays(dayOffset.toLong())
    val from: Instant = startDate.atStartOfDay(ZoneId.systemDefault()).toInstant()
    val to: Instant = startDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant()

    try {
        // Call the getStatistics method for each day
        val statistics = spikeConnection.getStatistics(
            types = setOf(StatisticsType.STEPS),
            from = from,
            to = to,
            interval = StatisticsInterval.DAY,
            filter = StatisticsFilter(providers = listOf(Provider.HEALTH_CONNECT))
        )
        
        // Process the statistics data
        statistics.forEach { statistic ->
            println("Steps for ${statistic.start}: ${statistic.value}")
        }
    } catch (e: SecurityException) {
        // Handle permission-related errors
        println("Permission denied. Guide user to Health Connect settings.")
    } catch (e: IllegalArgumentException) {
        // Handle invalid parameters
        println("Invalid request parameters: ${e.message}")
    } catch (e: Exception) {
        // Handle other errors gracefully
        println("Error fetching statistics for $startDate: ${e.localizedMessage}")
    }
}

Best Practices

Performance and User Experience

  • Keep the backfill process asynchronous for the best user experience
  • Segment requests into smaller date ranges to ensure optimal performance
  • Implement efficient data synchronization to minimize battery usage
  • Consider implementing a progress indicator for longer backfill operations
  • Use background processing where appropriate to avoid blocking the UI

Privacy and Security

  • Handle permissions gracefully - users may grant partial access
  • Consider allowing users to control the backfill scope (date range, data types)
  • Comply with relevant regulations such as GDPR for user data protection

Permission Management

  • Ensure your app handles the 30-day limitation appropriately
  • Consider implementing PERMISSION_READ_HEALTH_DATA_HISTORY for Android 14+ devices
  • Guide users to Health Connect settings when permissions are denied
  • Regularly check permission status and handle revoked permissions gracefully

Error Handling and Data Management

  • Implement robust error handling for various exception types
  • Gracefully handle scenarios where data is unavailable or incomplete
  • Manage data conflicts and duplicates effectively to maintain data integrity
  • Store health data securely using Android’s encryption and security best practices
  • Validate data before processing to ensure accuracy and consistency