> ## Documentation Index
> Fetch the complete documentation index at: https://docs.junction.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Junction Health SDK

> Overview of the Junction Health SDK for integrating with Apple HealthKit and Android Health Connect, including setup and common API usage.

## Overview

<Note>
  Make sure you have successfully integrated with a Junction Mobile SDK authentication scheme, before you proceed
  to try out Junction Health SDK.

  <Card title="Mobile SDK Authentication" icon="id-card" href="/wearables/sdks/authentication" horizontal>
    Learn how to authenticate your mobile app user with Junction Mobile SDK.
  </Card>
</Note>

This Junction Health SDK guidance page focuses on the initial setup and API usage of the Health SDK that is common to
Apple HealthKit, Android Health Connect, and Samsung Health integrations, where supported.

Please consult the following guides on requirements and restrictions of Apple HealthKit, Android Health Connect, and
Samsung Health:

<Card title="Apple HealthKit" icon="apple" href="/wearables/guides/apple-healthkit" horizontal>
  Learn how to integrate with Apple HealthKit through Junction Mobile SDKs, available in
  Native iOS, React Native and Flutter.
</Card>

<Card title="Android Health Connect" icon="android" href="/wearables/guides/android-health-connect" horizontal>
  Learn how to integrate with Android Health Connect through Junction Mobile SDKs, available in
  Native Android, React Native and Flutter.
</Card>

<Card title="Samsung Health" icon="heart" iconType="solid" href="/wearables/guides/samsung-health" horizontal>
  Learn how to integrate with Samsung Health through Junction Mobile SDKs, available in
  Native Android and React Native.
</Card>

## Initial Setup

### Review the Connection Policy options

Junction Health SDK has two Connection Policy options:

* The default [Auto Connect](/wearables/sdks/health/connection-policies#auto-connect-mode-default) mode; and

* The opt-in [Explicit Connect](/wearables/sdks/health/connection-policies#explicit-connect-mode) mode.

If your device connection management UX is built upon an explicit notion of connecting and disconnecting Apple HealthKit,
Health Connect and Samsung Health connections — as if they are like their cloud-based counterparts — you might find the [Explicit Connect](/wearables/sdks/health/connection-policies#explicit-connect-mode)
mode more appealing.

### iOS apps: Configure your App Delegate

This section applies to:

* 🔘 Native iOS apps
* 🔘 React Native iOS apps

This section does not apply to:

* ❌ Flutter iOS apps (using Junction Flutter SDK 4.3.8 or later).

<Note>
  Junction **Flutter** SDK (4.3.8 and later) automatically integrates with your App Delegate through the Flutter Plugin machinery.
  You need not manually edit your AppDelegate in **Flutter** iOS projects.
</Note>

<Warning>
  You must configure your App Delegate as instructed if you use Junction Health SDK on iOS. Not doing so
  may result in missing background delivery, or app process termination by the operating system.
</Warning>

In your AppDelegate's `application(_:didFinishLaunchingWithOptions:)` implementation, it **must** call Junction Health SDK
`automaticConfiguration()` synchronously before it returns.

<Accordion title="Details" icon="apple" defaultOpen>
  Junction needs to register various handlers with the system frameworks like Apple HealthKit and BackgroundTasks. These frameworks
  require said registrations to be completed **before** the "app finished launching" moment [\[1\]](https://developer.apple.com/documentation/healthkit/hkhealthstore/1614175-enablebackgrounddelivery#3801028)
  [\[2\]](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler/register\(fortaskwithidentifier:using:launchhandler:\)#Discussion).

  For React Native apps, the AppDelegate is part of the template Swift or Objective-C code in your generated Xcode project.

  <CodeGroup>
    ```swift Swift theme={null}
    import VitalHealthKit

    class AppDelegate: NSObject, UIApplicationDelegate {
      func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
      ) -> Bool {

        VitalHealthKitClient.automaticConfiguration()

        // ...

        return true
      }
    }
    ```

    ```objc Objective-C / React Native theme={null}
    #import "AppDelegate.h"
    #import "VitalHealthKitConfiguration.h"

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

      [VitalHealthKitConfiguration automaticConfiguration];

      // ...

      return YES;
    }
    ```
  </CodeGroup>
</Accordion>

### Configure the Junction Health SDK

The Health SDK must be configured before use.

The configuration is persistent, so you typically only need to do this a single time — immediately after
[a successful authentication with the Core SDK](/wearables/sdks/authentication).

<Tip>
  Health Connect and Samsung Health are two independent SDK integrations on Android, despite sharing the same
  Health SDK API. If you intend to use both integrations, you must configure both of them explicitly.
</Tip>

<Note>
  For Android *via* Expo and React Native, the Health SDK API assumes Health Connect by default. To target Samsung Health, you must
  pass `"samsung_health"` to the `provider` argument when calling the API.
</Note>

<CodeGroup>
  ```swift Native iOS theme={null}
  import VitalHealthKit

  VitalHealthKitClient.configure(
    VitalHealthKitClient.Configuration(
      backgroundDeliveryEnabled: true,

      // Using Auto Connect mode (default)
      connectionPolicy: .autoConnect

      // Using Explicit Connect mode
      connectionPolicy: .explicit
    )
  )
  ```

  ```kotlin Native Android theme={null}

  /**
   * Configure Health Connect
   */
  import io.tryvital.vitalhealthconnect.VitalHealthConnectManager
  import io.tryvital.vitalhealthcore.model.ConnectionPolicy

  val manager = VitalHealthConnectManager.configure(context)
  manager.configureHealthConnectClient(
    syncNotificationBuilder = null,

    // Using Auto Connect mode (default)
    connectionPolicy = ConnectionPolicy.AutoConnect

    // Using Explicit Connect mode
    connectionPolicy = ConnectionPolicy.Explicit

  )

  /**
   * Configure Samsung Health
   */
  import io.tryvital.vitalsamsunghealth.VitalSamsungHealthManager
  import io.tryvital.vitalhealthcore.model.ConnectionPolicy

  val manager = VitalSamsungHealthManager.configure(context)
  manager.configureSamsungHealthClient(
    syncNotificationBuilder = null,

    // Using Auto Connect mode (default)
    connectionPolicy = ConnectionPolicy.AutoConnect

    // Using Explicit Connect mode
    connectionPolicy = ConnectionPolicy.Explicit

  )
  ```

  ```typescript Expo & React Native theme={null}
  import { Platform } from "react-native";
  import {
    HealthConfig,
    VitalHealth,
  } from "@tryvital/vital-health-react-native";

  let config = new HealthConfig();

  config.iOSConfig.backgroundDeliveryEnabled = true;

  // Using Auto Connect mode (default)
  config.connectionPolicy = "autoConnect";

  // Using Explicit Connect mode
  config.connectionPolicy = "explicit";

  // Configure only Apple HealthKit (iOS) or Health Connect (Android)
  await VitalHealth.configure(config);

  // Configure only Samsung Health
  await VitalHealth.configure(config, "samsung_health");

  // Configure both Health Connect and Samsung Health
  await VitalHealth.configure(config, "health_connect");
  await VitalHealth.configure(config, "samsung_health");
  ```

  ```dart Flutter theme={null}
  import 'package:vital_health/vital_health.dart' as vital_health;

  await vital_health.configure(
    config: const vital_health.HealthConfig(
      iosConfig: vital_health.IosHealthConfig(
        backgroundDeliveryEnabled: true,
      ),

      // Using Auto Connect mode (default)
      connectionPolicy: vital_health.ConnectionPolicy.autoConnect,

      // Using Explicit Connect mode
      connectionPolicy: vital_health.ConnectionPolicy.explicit,
    ),
  );
  ```
</CodeGroup>

## Health Data Permissions

### Ask user for health data permissions

Before the SDK can read any data, you need to ask the end user to grant health data permissions.

<Note>
  For Android *via* Expo and React Native, the Health SDK API assumes Health Connect by default. To target Samsung Health, you must
  pass `"samsung_health"` to the `provider` argument when calling the API.
</Note>

<CodeGroup>
  ```swift Native iOS theme={null}
  import VitalHealthKit

  await VitalHealthKitClient.shared.ask(
    readPermissions: [.activity, .workout, .sleep],
    writePermissions: []
  )
  ```

  ```kotlin Native Android theme={null}

  //
  // Android Compose
  //

  import androidx.activity.compose.rememberLauncherForActivityResult
  import androidx.compose.runtime.rememberCoroutineScope
  import androidx.compose.material3.*
  import io.tryvital.vitalhealthconnect.VitalHealthConnectManager

  val manager: VitalHealthConnectManager = ...
  val contract = manager.createPermissionRequestContract(
    readResources = set(
      VitalResource.Activity,
      VitalResource.Workout,
      VitalResource.Sleep,
    ),
    writeResources = emptySet(),
  )

  val coroutineScope = rememberCoroutineScope()
  val permissionsLauncher = rememberLauncherForActivityResult(contract) { outcomeAsync ->
    coroutineScope.launch {
      val outcome = outcomeAsync.await()
      Log.i("VitalPermissionOutcome", outcome.toString())
    }
  }

  Button(onClick = { permissionsLauncher.launch(Unit) }) {
    Text("Ask for permission")
  }

  //
  // AndroidX Activity Result API
  //
  import androidx.activity.ComponentActivity
  import io.tryvital.vitalhealthconnect.VitalHealthConnectManager

  val activity: ComponentActivity = ...
  val manager: VitalHealthConnectManager = ...

  activity.registerForActivityResult(contract) { outcomeAsync ->
    CoroutineScope(Dispatchers.Main).launch {
      val outcome = outcomeAsync.await()
      Log.i("VitalPermissionOutcome", outcome.toString())
    }
  }
  ```

  ```typescript Expo & React Native theme={null}
  import { Platform } from "react-native";
  import {
    VitalHealth,
    VitalResource,
  } from "@tryvital/vital-health-react-native";

  // Apple HealthKit (iOS) or Health Connect (Android)
  await VitalHealth.ask(
      [VitalResource.Activity, VitalResource.Workout, VitalResource.Sleep],
      [],
      undefined,
  );

  // Samsung Health
  await VitalHealth.ask(
      [VitalResource.Activity, VitalResource.Workout, VitalResource.Sleep],
      [],
      undefined,
      "samsung_health"
  );
  ```

  ```dart Flutter theme={null}
  import 'package:vital_health/vital_health.dart' as vital_health;

  final List<vital_health.HealthResource> readResources = [
    vital_health.HealthResource.activity,
    vital_health.HealthResource.sleep,
    vital_health.HealthResource.workout,
  ];
  await vital_health.askForPermission(readResources, []);
  ```
</CodeGroup>

Regardless of whether the user has granted or denied the permissions, any subsequent re-request would
be non-interactive and return instantly. This is because the operating system only prompts the end user
once for each resource type.

<Warning>
  The health data read permission prompt is managed by the operating system. Junction cannot customize or
  alter its behavior.
</Warning>

### Check if your app has asked for permissions before

You can check if your app has already asked the user *at least once* before, for permissions on a specific `VitalResource`.

Because [Ask for Permission](#ask-user-for-health-data-permissions) is gracefully ignored by the operating system beyond
the first time, checking before asking can help you skip the parts of your UX journey that only make sense to users
going through [Ask for Permission](#ask-user-for-health-data-permissions) for the first time.

The only exception to this behavior is when a `VitalResource` pulls a new data type introduced in a new OS release.
In this scenario, calling [Ask for Permission](#ask-user-for-health-data-permissions) would result in an OS permission
prompt that asks for permissions on *specifically* those new data types.

If you wish
to provide a way for users to review their permission grants or denials, you can
[inform them of the system app location where they can do so](#check-if-a-read-permission-was-granted-or-denied-spoiler-you-cant).

<Note>
  For Android *via* Expo and React Native, the Health SDK API assumes Health Connect by default. To target Samsung Health, you must
  pass `"samsung_health"` to the `provider` argument when calling the API.
</Note>

<CodeGroup>
  ```swift Native iOS theme={null}
  import VitalHealthKit

  VitalHealthKitClient.shared.hasAskedForPermission(resource: .activity)
  ```

  ```kotlin Native Android theme={null}
  import io.tryvital.vitalhealthconnect.VitalHealthConnectManager

  val manager = VitalHealthConnectManager.configure(context)
  manager.hasAskedForPermission(VitalResource.Activity)
  ```

  ```typescript Expo & React Native theme={null}
  import { Platform } from "react-native";
  import {
    VitalHealth,
    VitalResource,
  } from "@tryvital/vital-health-react-native";

  // Apple HealthKit (iOS) or Health Connect (Android)
  await VitalHealth.hasAskedForPermission(VitalResource.Activity, provider);

  // Samsung Health
  await VitalHealth.hasAskedForPermission(VitalResource.Activity, "samsung_health");
  ```

  ```dart Flutter theme={null}
  import 'package:vital_health/vital_health.dart' as vital_health;

  await vital_health.hasAskedForPermission(vital_health.HealthResource.Activity);
  ```
</CodeGroup>

### Check if a read permission was granted or denied (⚠️ Spoiler: You can't)

Junction Health SDK allows you to [ask for permission](#ask-user-for-health-data-permissions) and
[check if your app has asked for permission before](#check-if-your-app-has-asked-for-permissions-before).

However, Junction Health SDK **cannot** tell you:

1. Whether or not a user has granted or denied a read permission after the [Ask for Permission](#ask-user-for-health-data-permissions) has concluded.
2. The state of a read permission at any exact moment — granted or denied.

Apple made a deliberate choice to conceal the state of HealthKit data type read permissions from third-party apps.
Quoting [Apple's own words](https://developer.apple.com/documentation/healthkit/hkhealthstore/1614154-authorizationstatus) (as at 27 September 2024):

> To help prevent possible leaks of sensitive health information, your app cannot determine whether or not a user has granted permission to read data.
>
> If you are not given permission, it simply appears as if there is no data of the requested type in the HealthKit store.
>
> \[...]

In other words, all third-party apps — including anyone using the Junction Health SDK — would:

1. not be able to determine if a particular read permission has been granted or denied by the user;

2. not be able to manage or review read permissions inside their app.

The best course of action out of this is to inform your users of the location where they can review and manage their health data read permissions:

| Operating System     | System App         | Location                              |
| -------------------- | ------------------ | ------------------------------------- |
| iOS 8.0 and above    | Health app         | Sharing > Apps and Services           |
| iOS 15.0 and above   | Settings app       | Privacy & Security > Health           |
| Android 13 or below  | Health Connect app | Apps and Permissions                  |
| Android 14 and above | Settings app       | Health Connect > Apps and Permissions |

<Note>
  When designing your user experience, **assume** you would have zero knowledge of
  permission grants and denials after the user has gone through the [Ask for Permission](#ask-user-for-health-data-permissions) flow.
</Note>

## Automatic Data Sync

Junction Health SDK automates data sync for you on both Android and iOS. Please first consult
the provider-specific guides for the requirements and setup instructions:

* [Apple HealthKit guide](/wearables/guides/apple-healthkit)
* [Android Health Connect guide](/wearables/guides/android-health-connect)
* [Samsung Health guide](/wearables/guides/samsung-health)

### iOS

| Sync is automatically... |                                                                                                                                                                                             |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Activated on             | All resource types you have [asked permission for](#ask-user-for-health-data-permissions).                                                                                                  |
| Triggered by             | Two behaviors: <ul><li>Foreground: Apple HealthKit immediately delivers buffered and new changes.</li><li>Background: Hourly batch delivery of changes, subject to OS throttling.</li></ul> |

<Note>
  HealthKit change notification is an always-on behavior.

  If you did not configure [Apple HealthKit Background Delivery](/wearables/guides/apple-healthkit)
  as instructed, your app will not receive any HealthKit change notification while it is in background.
  In turn, background sync would not occur.
</Note>

### Android

| Sync is automatically... |                                                                                                |
| ------------------------ | ---------------------------------------------------------------------------------------------- |
| Activated on             | All resource types you have [asked permission for](#ask-user-for-health-data-permissions).     |
| Triggered by             | Two mechanisms: <ul><li>Sync On App Launch</li><li>Background Sync if it is enabled.</li></ul> |

<Note>
  Sync On App Launch is an always-on behavior. Background Sync is an **opt-in** behavior.

  Please refer to the [Android Health Connect guide](/wearables/guides/android-health-connect) or
  the [Samsung Health guide](/wearables/guides/samsung-health) for the full context and required configuration
  of these two behaviors.
</Note>

### Background Sync Frequency

Junction Health SDK schedules hourly background sync with Apple HealthKit, Android Health Connect and Samsung Health,
provided that you have:

1. Configured [Apple HealthKit Background Delivery](/wearables/guides/apple-healthkit) as per instructions; and
2. Configured Android Background Sync for the provider you are using — [Health Connect](/wearables/guides/android-health-connect#background-sync)
   or [Samsung Health](/wearables/guides/samsung-health#background-sync) — and request user permissions (when necessary) as per instructions.

However, this schedule is only advisory. The OS has full discretion to defer the scheduled time based on runtime
constraints like battery power, as well as platform background execution policies. For a more detailed explanation, please refer to:

* [Apple HealthKit: Sync Frequency](/wearables/guides/apple-healthkit#sync-frequency)
* [Android Health Connect: Synchronization](/wearables/guides/android-health-connect#synchronization)
* [Samsung Health: Background Sync](/wearables/guides/samsung-health#background-sync)

In other words, your product experience should not assume near real-time availability of wearable data, since the norm
is a variable delay ranging from an hour to a day. Longer delay is also possible due to the lack of Internet
connectivity, e.g., a long-haul flight, or an off-the-grid trip.

The only possible exception is when your product experience does involve
**active usage** of your consumer app with an active Internet connection. For example, iOS 17+ supports third-party
apps initiating an Apple Watch workout session that would be live synced with your iPhone app.

### Pausing Data Synchronization

You can pause and unpause data sync at any time, without having to sign out the user from the Junction Mobile SDK.
Note that pausing data sync does not reset the incremental sync progress and does not trigger a historical stage
upon unpause. It only "freezes" the sync progress.

<Note>
  For Android *via* Expo and React Native, the Health SDK API assumes Health Connect by default. To target Samsung Health, you must
  pass `"samsung_health"` to the `provider` argument when calling the API.
</Note>

<CodeGroup>
  ```swift Native iOS theme={null}
  import VitalHealthKit

  // Pause Synchronization
  VitalHealthKitClient.shared.pauseSynchronization = true

  // Unpause Synchronization
  VitalHealthKitClient.shared.pauseSynchronization = false

  // Check if synchronization is paused
  print("Paused? \(VitalHealthKitClient.shared.pauseSynchronization)")
  ```

  ```kotlin Native Android theme={null}
  import io.tryvital.vitalhealthconnect.VitalHealthConnectManager

  val manager = VitalHealthConnectManager.getOrCreate(context)

  // Pause Synchronization
  manager.pauseSynchronization = true

  // Unpause Synchronization
  manager.pauseSynchronization = false

  // Check if synchronization is paused
  Log.i("sync", "Paused? ${manager.pauseSynchronization}")
  ```

  ```typescript Expo & React Native theme={null}
  import { Platform } from "react-native";
  import {
    VitalHealth,
  } from "@tryvital/vital-health-react-native";

  // Pause Synchronization
  await VitalHealth.setPauseSynchronization(true);
  await VitalHealth.setPauseSynchronization(true, "apple_health_kit");
  await VitalHealth.setPauseSynchronization(true, "health_connect");
  await VitalHealth.setPauseSynchronization(true, "samsung_health");

  // Unpause Synchronization
  await VitalHealth.setPauseSynchronization(false);
  await VitalHealth.setPauseSynchronization(false, "apple_health_kit");
  await VitalHealth.setPauseSynchronization(false, "health_connect");
  await VitalHealth.setPauseSynchronization(false, "samsung_health");

  // Check if synchronization is paused
  const isPaused = await VitalHealth.isProviderSynchronizationPaused();
  const isPaused = await VitalHealth.isProviderSynchronizationPaused("apple_health_kit");
  const isPaused = await VitalHealth.isProviderSynchronizationPaused("health_connect");
  const isPaused = await VitalHealth.isProviderSynchronizationPaused("samsung_health");
  ```

  ```dart Flutter theme={null}
  import 'package:vital_health/vital_health.dart' as vital_health;

  // Pause Synchronization
  await vital_health.setPauseSynchronization(true);

  // Unpause Synchronization
  await vital_health.setPauseSynchronization(false);

  // Check if synchronization is paused
  final isPaused = await vital_health.pauseSynchronization;
  ```
</CodeGroup>

## Sync Status

You can observe the `syncStatus` stream for continuous updates on the health data sync status.

<CodeGroup>
  ```swift Native iOS theme={null}
  import VitalHealthKit

  VitalHealthKitClient.shared.status.sink { status in
    print("Sync Status: \(status)")
  }
  ```

  ```kotlin Native Android theme={null}
  import io.tryvital.vitalhealthconnect.VitalHealthConnectManager
  import kotlinx.coroutines.*
  import kotlinx.coroutines.flow.*

  val coroutineScope: CoroutineScope
  val manager = VitalHealthConnectManager.getOrCreate(context)

  manager.status
    .onEach { status -> Log.i("HealthDataSync", "$status") }
    .launchIn(coroutineScope)
  ```

  ```typescript Expo & React Native theme={null}
  import { Platform } from "react-native";
  import {
    AndroidHealthProvider,
    IOSHealthProvider,
    VitalHealth,
  } from "@tryvital/vital-health-react-native";

  // Apple HealthKit (iOS) or Health Connect (Android)
  const subscription = VitalHealth.observeSyncStatusChange((status) => {
    console.log("Sync Status", status);
  });

  // Samsung Health
  const subscription = VitalHealth.observeSyncStatusChange((status) => {
    console.log("Sync Status", status);
  }, "samsung_health");

  // later
  subscription.remove();
  ```

  ```dart Flutter theme={null}
  import 'package:vital_health/vital_health.dart' as vital_health;

  Stream<SyncStatus> status = vital_health.syncStatus;
  ```
</CodeGroup>

## Sync Progress Debugging UI (iOS only)

<AccordionGroup>
  <Accordion title="Sync Progress View on Native iOS" defaultOpen>
    Junction Health SDK for iOS includes a `ForEachVitalResource` — a pre-baked SwiftUI View providing a
    live-updated sync progress feed of all the `VitalResource`s whose permissions have been asked for.

    You can use `ForEachVitalResource()` in any position which you would use `ForEach`. For example,
    you can use it inside a `Section` of a `List`:

    ```swift Native iOS theme={null}
    import VitalHealthKit

    struct SyncProgressView: View {
      var view: some View {
        List {
          Section(header: Text("Sync Progress")) {
            ForEachVitalResource()
          }
        }
      }
    }
    ```

    If you are using UIKit, you can still access it through `UIHostingController`:

    ```swift Native iOS theme={null}
    let viewController: UIViewController

    let hostingController = UIHostingController(rootView: SyncProgressView())
    viewController.present(hostingController, animated: true, completion: nil)
    ```
  </Accordion>

  <Accordion title="Sync Progress UI on Flutter / React Native" defaultOpen>
    You can open the Apple HealthKit Sync Progress Inspector UI through a simple call:

    <CodeGroup>
      ```dart Flutter theme={null}
      import 'package:vital_health/vital_health.dart' as vital_health;

      unawaited(vital_health.openSyncProgressView());
      ```

      ```typescript Expo & React Native theme={null}
      import {
        IOSHealthProvider,
        VitalHealth,
      } from "@tryvital/vital-health-react-native";

      await VitalHealth.openSyncProgressView();
      ```
    </CodeGroup>

    This Sync Progress Inspector UI provides a live-updated sync progress feed of all the VitalResources whose permissions have been asked for.

    <Note>
      Note that it is currently a no-op on Android.
    </Note>
  </Accordion>
</AccordionGroup>

## Persistent Logging (iOS only)

While Junction Dashboard provides a fairly comprehensive Mobile SDK Sync Progress view, the reporting mechanism
can only include condensed and headline information in order to conserve network bandwidth usage.

In order to troubleshoot data sync issues that are non-reproducible in controlled environments, the Health
SDK supports **opt-in** Persistent Logging which would keep logs on disk across application launches.

<Tip>
  The archive file is simply an Apple Archive (aar) containing various JSON files and plain text logs. Your app developers
  are welcome to dig into it for a self-troubleshooting attempt.
</Tip>

<CodeGroup>
  ```swift iOS theme={null}
  import VitalCore
  import VitalHealthKit

  // Toggle Persistent Logging
  // ℹ️ Note that this persists across application launches.
  VitalPersistentLogger.isEnabled = true

  // Generate the archive file, and open the system Share Sheet.
  VitalHealthKitClient.createAndShareLogArchive()
  ```

  ```typescript Expo & React Native theme={null}
  import {
    VitalHealth,
  } from "@tryvital/vital-health-react-native";

  // Toggle Persistent Logging
  // ℹ️ Note that this persists across application launches.
  await VitalHealth.setPersistentLoggingEnabled(true);

  // Check if Persistent Logging is enabled.
  const isEnabled = await VitalHealth.isPersistentLoggingEnabled();

  // Generate the archive file, and open the system Share Sheet.
  await VitalHealth.sharePersistentLogArchive(true);
  ```
</CodeGroup>

You can introduce a couple of simple UI controls in a non-prominent location in your user experience, e.g., the app settings screen:

* A "Capture Sync Issues" switch, which toggles the SDK Persistent Logging.
* A "Share the Capture" button, which triggers the archive file generate-and-share flow.

Then on an as-needed basis, your support team can:

1. Instruct users to enable capturing; and
2. In a few days' time, share the capture (archive file) with you.

<Note>
  Junction may also require your support team's help to obtain an archive file, in order to make progress on any non-reproducible issue reports.
</Note>
