@devmaxime/capacitor-health-extended
v0.1.4
Published
Capacitor plugin for Apple HealthKit and Google Health Connect Platform
Maintainers
Readme
capacitor-health-extended
Cross‑platform Capacitor plugin for reading data from Apple HealthKit and Google Health Connect. The plugin requires Node.js 20+ and is compatible with Capacitor 7.
Thanks and attribution
Forked from capacitor-health and as such...
- Some parts, concepts and ideas are borrowed from cordova-plugin-health.
- Big thanks to @dariosalvi78 for the support.
Thanks @mley for the ground work. The goal of this fork is to extend functionality and datapoints and keep up with the ever-changing brand-new Android Health Connect Platform. I'm hoping to create platform parity for capacitor API-based health data access.
Requirements
- Node.js 20 or newer
- Capacitor 7
Features
- Check if health functionality is available on the device
- Request and verify health permissions
- Query aggregated data like steps or calories
- Retrieve workout sessions with optional route and heart rate data
- Fetch the latest sample for steps, heart‑rate, or weight
Install
npm install capacitor-health-extended
npx cap syncSetup
iOS
- Make sure your app id has the 'HealthKit' entitlement when this plugin is installed (see iOS dev center).
- Also, make sure your app and App Store description comply with the Apple review guidelines.
- There are two keys to be added to the info.plist file: NSHealthShareUsageDescription and NSHealthUpdateUsageDescription.
Android
- Android Manifest in root tag right after opening manifest tag
<!-- Make Health Connect visible to detect installation -->
<queries>
<package android:name="com.google.android.apps.healthdata" />
</queries>
<!-- Declare permissions you’ll request -->
<uses-permission android:name="android.permission.health.READ_STEPS" />
<uses-permission android:name="android.permission.health.READ_ACTIVE_CALORIES_BURNED" />
<uses-permission android:name="android.permission.health.READ_TOTAL_CALORIES_BURNED" />
<uses-permission android:name="android.permission.health.READ_DISTANCE" />
<uses-permission android:name="android.permission.health.READ_EXERCISE" />
<uses-permission android:name="android.permission.health.READ_EXERCISE_ROUTE" />
<uses-permission android:name="android.permission.health.READ_HEART_RATE" />
<uses-permission android:name="android.permission.health.READ_WEIGHT" />
<uses-permission android:name="android.permission.health.READ_HEIGHT" />
<uses-permission android:name="android.permission.health.READ_HEART_RATE_VARIABILITY" />
<uses-permission android:name="android.permission.health.READ_BLOOD_PRESSURE" />- Android Manifest in application tag
<!-- Handle Health Connect rationale (Android 13-) -->
<activity
android:name=".PermissionsRationaleActivity"
android:exported="true">
<intent-filter>
<action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE"/>
<category android:name="android.intent.category.HEALTH_PERMISSIONS"/>
</intent-filter>
</activity>
<!-- Handle Android 14+ alias -->
<activity-alias
android:name="ViewPermissionUsageActivity"
android:exported="true"
android:targetActivity=".PermissionsRationaleActivity"
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>- Android Manifest in application tag for secure WebView content
<!-- Configure secure WebView and allow HTTPS loading -->
<application
android:usesCleartextTraffic="false"
android:networkSecurityConfig="@xml/network_security_config">
...
</application>- Create
res/xml/network_security_config.xmlwith:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>This setup ensures your WebView will load HTTPS content securely and complies with Android's default network security policy.
API
<docgen-index>
* [`isHealthAvailable()`](#ishealthavailable)
* [`checkHealthPermissions(...)`](#checkhealthpermissions)
* [`requestHealthPermissions(...)`](#requesthealthpermissions)
* [`openAppleHealthSettings()`](#openapplehealthsettings)
* [`openHealthConnectSettings()`](#openhealthconnectsettings)
* [`showHealthConnectInPlayStore()`](#showhealthconnectinplaystore)
* [`queryAggregated(...)`](#queryaggregated)
* [`queryWorkouts(...)`](#queryworkouts)
* [`queryLatestSample(...)`](#querylatestsample)
* [`queryWeight()`](#queryweight)
* [`queryHeight()`](#queryheight)
* [`queryHeartRate()`](#queryheartrate)
* [`querySteps()`](#querysteps)
* [Interfaces](#interfaces)
* [Type Aliases](#type-aliases)
</docgen-index>isHealthAvailable()
isHealthAvailable() => Promise<{ available: boolean; }>Checks if health API is available. Android: If false is returned, the Google Health Connect app is probably not installed. See showHealthConnectInPlayStore()
Returns: Promise<{ available: boolean; }>
checkHealthPermissions(...)
checkHealthPermissions(permissions: PermissionsRequest) => Promise<PermissionResponse>Android only: Returns for each given permission, if it was granted by the underlying health API
| Param | Type | Description |
| ----------------- | ----------------------------------------------------------------- | -------------------- |
| permissions | PermissionsRequest | permissions to query |
Returns: Promise<PermissionResponse>
requestHealthPermissions(...)
requestHealthPermissions(permissions: PermissionsRequest) => Promise<PermissionResponse>Requests the permissions from the user.
Android: Apps can ask only a few times for permissions, after that the user has to grant them manually in the Health Connect app. See openHealthConnectSettings()
iOS: If the permissions are already granted or denied, this method will just return without asking the user. In iOS we can't really detect if a user granted or denied a permission. The return value reflects the assumption that all permissions were granted.
| Param | Type | Description |
| ----------------- | ----------------------------------------------------------------- | ---------------------- |
| permissions | PermissionsRequest | permissions to request |
Returns: Promise<PermissionResponse>
openAppleHealthSettings()
openAppleHealthSettings() => Promise<void>Opens the apps settings, which is kind of wrong, because health permissions are configured under: Settings > Apps > (Apple) Health > Access and Devices > [app-name] But we can't go there directly.
openHealthConnectSettings()
openHealthConnectSettings() => Promise<void>Opens the Google Health Connect app
showHealthConnectInPlayStore()
showHealthConnectInPlayStore() => Promise<void>Opens the Google Health Connect app in PlayStore
queryAggregated(...)
queryAggregated(request: QueryAggregatedRequest) => Promise<QueryAggregatedResponse>Query aggregated data
| Param | Type |
| ------------- | ------------------------------------------------------------------------- |
| request | QueryAggregatedRequest |
Returns: Promise<QueryAggregatedResponse>
queryWorkouts(...)
queryWorkouts(request: QueryWorkoutRequest) => Promise<QueryWorkoutResponse>Query workouts
| Param | Type |
| ------------- | ------------------------------------------------------------------- |
| request | QueryWorkoutRequest |
Returns: Promise<QueryWorkoutResponse>
queryLatestSample(...)
queryLatestSample(request: { dataType: string; }) => Promise<QueryLatestSampleResponse>Query latest sample for a specific data type
| Param | Type |
| ------------- | ---------------------------------- |
| request | { dataType: string; } |
Returns: Promise<QueryLatestSampleResponse>
queryWeight()
queryWeight() => Promise<QueryLatestSampleResponse>Query latest weight sample
Returns: Promise<QueryLatestSampleResponse>
queryHeight()
queryHeight() => Promise<QueryLatestSampleResponse>Query latest height sample
Returns: Promise<QueryLatestSampleResponse>
queryHeartRate()
queryHeartRate() => Promise<QueryLatestSampleResponse>Query latest heart rate sample
Returns: Promise<QueryLatestSampleResponse>
querySteps()
querySteps() => Promise<QueryLatestSampleResponse>Query latest steps sample
Returns: Promise<QueryLatestSampleResponse>
Interfaces
PermissionResponse
| Prop | Type |
| ----------------- | ------------------------------------------ |
| permissions | { [key: string]: boolean; }[] |
PermissionsRequest
| Prop | Type |
| ----------------- | ------------------------------- |
| permissions | HealthPermission[] |
QueryAggregatedResponse
| Prop | Type |
| -------------------- | ------------------------------- |
| aggregatedData | AggregatedSample[] |
AggregatedSample
| Prop | Type |
| --------------- | ------------------- |
| startDate | string |
| endDate | string |
| value | number |
QueryAggregatedRequest
| Prop | Type |
| --------------- | --------------------------------------------------------------------------------------- |
| startDate | string |
| endDate | string |
| dataType | 'steps' | 'active-calories' | 'mindfulness' | 'hrv' | 'blood-pressure' |
| bucket | string |
QueryWorkoutResponse
| Prop | Type |
| -------------- | ---------------------- |
| workouts | Workout[] |
Workout
| Prop | Type |
| -------------------- | ------------------------------ |
| startDate | string |
| endDate | string |
| workoutType | string |
| sourceName | string |
| id | string |
| duration | number |
| distance | number |
| steps | number |
| calories | number |
| sourceBundleId | string |
| route | RouteSample[] |
| heartRate | HeartRateSample[] |
RouteSample
| Prop | Type |
| --------------- | ------------------- |
| timestamp | string |
| lat | number |
| lng | number |
| alt | number |
HeartRateSample
| Prop | Type |
| --------------- | ------------------- |
| timestamp | string |
| bpm | number |
QueryWorkoutRequest
| Prop | Type |
| ---------------------- | -------------------- |
| startDate | string |
| endDate | string |
| includeHeartRate | boolean |
| includeRoute | boolean |
| includeSteps | boolean |
QueryLatestSampleResponse
| Prop | Type |
| --------------- | ------------------- |
| value | number |
| systolic | number |
| diastolic | number |
| timestamp | number |
| unit | string |
Type Aliases
HealthPermission
'READ_STEPS' | 'READ_WORKOUTS' | 'READ_ACTIVE_CALORIES' | 'READ_TOTAL_CALORIES' | 'READ_DISTANCE' | 'READ_WEIGHT' | 'READ_HEIGHT' | 'READ_HEART_RATE' | 'READ_ROUTE' | 'READ_MINDFULNESS' | 'READ_HRV' | 'READ_BLOOD_PRESSURE'
