Migrate Health Connect from Android 13 (APK) to Android 14 (framework)

Health Connect will be packaged with Android 14 as a common data storage layer for consumer health data, protected by granular permissions and accessible as an Android system app (referred to throughout this document as the 'framework' module).

Developers should consider the Health Connect APK (Android 13) as a backwards compatibility layer for the framework model. The framework model will retain 100% feature parity with its APK predecessor.

During the transition from Android 13 to 14, it's vitally important that the user experience remains as smooth and intuitive as possible.

This document outlines the migration plan, provides some example migration scenarios, and lists changes to the Jetpack SDK, which facilitates access to the Health Connect API.

Migration plan

  1. Once Android 14 is released, Google will switch to providing Health Connect as an Android system app.
  2. Data will then be backfilled from the APK once feature parity is achieved.
  3. All entry points will target the system app UI.
  4. Data migration will commence. Whilst the migration is progressing, the module APIs will be suspended with a 'Migration in Process' status. This will also be visible within the Health Connect UI.
  5. Once migration is complete, the APK can be uninstalled.

Example migration scenarios

Here are some example scenarios that explain the migration process for both interval and series data types:

Example 1 - Running (interval data)

A user has collected 10 years of running records for 1 hour every day. This equates to:

  • Exercise Session Records: 365 * 10 * 1
  • Steps: 365 * 10 * 1
  • Calories: 365 * 10 * 1
  • Total = 365 * 10 * 3 (365 * 30) = 10,150

Given that 1 chunk equates to 3,000 records, the above data totals around 4 chunks.

Our internal testing has confirmed that a typical chunk takes approximately a second to insert, so the above data would be migrated in approximately 4 seconds.

Example 2 - Heart rate (series data)

A user has collected 5 years of heart rate data (with a record created every minute) totalling 2,628,000 records.

At 3,000 records per chunk, the data is distributed across 876 chunks. Given that 1 chunk takes approximately a second to insert, the data would be migrated in under 15 minutes.

Proposed migration flow

We've decided to opt for an instant migration. In practical terms, this means that the APK will become inactive as soon as the device is upgraded to Android 14, with minimal user intervention.

Let's take a look at a high-level migration flow:

  1. The user upgrades their device to Android 14.
  2. Jetpack 14 routes the user to the module APIs, and blocks them whilst the migration is in progress.
  3. The migration process starts when the module version is feature compatible with the APK - i.e. the module version contains the same feature set, or more. Once the migration process has commenced, the APK migrates permissions and data.
    1. If both versions are not feature compatible, the module version will need to be upgraded. Once the upgrade is complete, the migration process will commence.
  4. Once the migration has completed, the state is changed to 'Migration Complete', and the module APIs are unblocked.
  5. The APK can now be uninstalled.

Migration UI elements

The following screens are displayed by the framework module for user education purposes, both before and during migration:

Figure 1. If the Health Connect APK is not 'migration aware', a prompt is displayed instructing the user to update the APK. If the user declines the update, the module continues to function and starts accumulating permissions and data:

Phone update required


Figure 2. If the framework module requires an update for it to become feature compatible, a prompt is displayed asking the user to perform the update and reboot their device. If the user declines the update, the module continues to function and starts accumulating permissions and data:

APK update needed


Figure 3. A spinner is displayed during the migration process, with text to explain that data is syncing:

Data Syncing

Deduped data

If the framework module has started to acquire data and permissions before any migration or cloud-based restore has taken place, the following rules apply.

Permissions

If permissions are present within the framework module, any duplicate permissions acquired from the APK are ignored during the migration process.

Data

During migration, duplicate data originating from the APK is ignored. More recent data from the module is given preference.

The data is deduped on clientRecordId if the record ID is provided by the client. If it isn't, time intervals (startTime and endTime for internal records, and time for instant records) are treated as key, along with the data type and package name of the app.

Changes in Jetpack SDK

The Jetpack SDK serves as the common integration point for both the Health Connect APK, and the Health Connect framework APIs.

OEMs can start integrating with Jetpack 13 so that when Jetpack 14 becomes available, you are able to appropriate the new library and compile it within Android 14.

We'll be releasing a new version of the SDK that supports the transition to Android 14. You will need to make some changes to your existing integration to ensure a smooth transition.

Permission declaration

In Android 13, you declare permissions using a custom permissions format, in a resource file that is linked to the manifest:

#AndroidManifest.xml

<activity>
    android:name=".RationaleActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE"/>
    </intent-filter>
    <meta-data
        android:name="health_permissions"
        android:resource="@array/health_permissions"/>
</activity>

<queries>
    <package android:name="com.google.android.apps.healthdata" />
</queries>

#health_permissions.xml

<resources>
  <array name="health_permissions">
    <item>androidx.health.permission.SleepSession.READ</item>
    <item>androidx.health.permission.SleepStage.READ</item>
    <item>androidx.health.permission.Weight.READ</item>
    <item>androidx.health.permission.Weight.WRITE</item>
  </array>
</resources>

To support Android 14, developers need to move to the standard permissions format:

#AndroidManifest.xml

<uses-permission android:name=”android.permission.health.READ_SLEEP” />
<uses-permission android:name=”android.permission.health.READ_WEIGHT” />
<uses-permission android:name=”android.permission.health.WRITE_WEIGHT” />

<activity>
    android:name=".RationaleActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
    </intent-filter>
</activity>

<queries>
    <package android:name="com.google.android.apps.healthdata"/>
</queries>

Open Health Connect

Most third-party apps feature a button that opens the Health Connect app, such as the 'Manage Access' button in Fitbit.

In Android 13, you either open the Health Connect app using the package name, or via the androidx.health.ACTION_HEALTH_CONNECT_SETTINGS action.

In Android 14, you need to use an intent action, specified in the Jetpack SDK, which has different values based on the Android version it's acting on:

@get:JvmName("getHealthConnectSettingsAction") @JvmStatic val ACTION_HEALTH_CONNECT_SETTINGS

Getting the Health Connect client

We've created a single API called sdkStatus, available in Jetpack 11, to replace two other deprecated APIs - IsSdkSupported() and isProviderAvailable().

Session record API changes

Four ExerciseSession subtypes have been deleted as part of the alpha10 release:

  • ExerciseEvent
  • ExerciseLaps
  • ExerciseRepetitions
  • SwimmingStrokes

As with ExerciseSessionRecord, SleepStage will become a subtype of SleepSession.

Both the ExerciseSessionRecord subtypes and SleepSession changes will be released as part of the April SDK update.

Exercise session type update

The below exercise session types will no longer be supported, and instead added as segment types at a later date:

  • EXERCISE_TYPE_BACK_EXTENSION
  • EXERCISE_TYPE_BARBELL_SHOULDER_PRESS
  • EXERCISE_TYPE_BENCH_PRESS
  • EXERCISE_TYPE_BENCH_SIT_UP
  • EXERCISE_TYPE_BURPEE
  • EXERCISE_TYPE_CRUNCH
  • EXERCISE_TYPE_DEADLIFT
  • EXERCISE_TYPE_DUMBBELL_CURL_LEFT_ARM
  • EXERCISE_TYPE_DUMBBELL_CURL_RIGHT_ARM
  • EXERCISE_TYPE_DUMBBELL_FRONT_RAISE
  • EXERCISE_TYPE_DUMBBELL_LATERAL_RAISE
  • EXERCISE_TYPE_DUMBBELL_TRICEPS_EXTENSION_LEFT_ARM
  • EXERCISE_TYPE_DUMBBELL_TRICEPS_EXTENSION_RIGHT_ARM
  • EXERCISE_TYPE_DUMBBELL_TRICEPS_EXTENSION_TWO_ARM
  • EXERCISE_TYPE_FORWARD_TWIST
  • EXERCISE_TYPE_JUMPING_JACK
  • EXERCISE_TYPE_JUMP_ROPE
  • EXERCISE_TYPE_LAT_PULL_DOWN
  • EXERCISE_TYPE_LUNGE
  • EXERCISE_TYPE_PLANK
  • EXERCISE_TYPE_SQUAT
  • EXERCISE_TYPE_UPPER_TWIST

Replacement types:

  • EXERCISE_TYPE_HIGH_INTENSITY_INTERVAL_TRAINING
  • EXERCISE_TYPE_STRENGTH_TRAINING
  • EXERCISE_TYPE_CALISTHENICS

Changelog handling

Changelogs will not be migrated as part of the switch from APK to Android 14.

After migration is complete, you will start to receive TOKEN_EXPIRED or TOKEN_INVALID exceptions. These should be handled in the following ways (in order of preference):

1. Read and dedupe all data since the 'last read' timestamp, or for the last 30 days

Store a timestamp of when an app last read data from Health Connect. On token expiry, data should be re-read either from this value, or the previous 30 days (whichever equates to the minimum), and dedupe it against previously read data using the UUID.

2. Read data since the 'last read' timestamp

Establish a timestamp that indicates when data was last read from Health Connect , and upon token expiry, read all data after that value.

3. Delete and re-read data for the last 30 days

Delete all data read from Health Connect from the previous 30 days, and read all of that data again (e.g. as is done when apps first integrate with Health Connect).

4. Do nothing (i.e. re-read data for the last 30 days and don't dedupe)

This should be used as a last resort, with an associated risk of displaying duplicate data. Developers should instead explore options 1-3, given that UUIDs should already be in place.

Testing Android 14 APIs with Jetpack SDK

The Android 14 Jetpack SDK is set to be released on June 7 2023, along with the Beta 3 release of Android 14. You will need to start compiling your app against Android 14 to be able to use the Android 14 Jetpack SDK.

If you wish to test your solution against the Android Developer Preview builds ahead of June 7th, contact your Google POC for assistance.

If you want to test your solution against the Beta 3 release, you should make the following changes in your APK:

  1. Set compileSDKPreview = UpsideDownCake.
  2. Update the manifest to include an intent for Android 14:
# AndroidManifest.xml

<uses-permission android:name=”android.permission.health.READ_SLEEP”/>
<uses-permission android:name=”android.permission.health.READ_WEIGHT”/>
<uses-permission android:name=”android.permission.health.WRITE_WEIGHT”/>

<activity>
    android:name=".RationaleActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE"/>
    </intent-filter>
</activity>

<activity-alias>
      android:name="AndroidURationaleActivity"
      android:exported="true"
      android:targetActivity=".RationaleActivity"
      android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
      <intent-filter>
        <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
        <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
      </intent-filter>
</activity-alias>

<queries>
    <package android:name="com.google.android.apps.healthdata" />
</queries>

OEM customization

In Android 14, Health Connect privacy & data management controls are located within System Settings.

To make data management and permissions screens look and feel like part of the device, Health Connect offers OEM theming through the use of custom overlays.

For documentation on OEM styling, consult Health Connect Google Mobile Services documentation.