
Product
Introducing Tier 1 Reachability: Precision CVE Triage for Enterprise Teams
Socket’s new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.
cordova-plugin-mhw-healthk
Advanced tools
A plugin that abstracts fitness and health repositories like Apple HealthKit or Google Fit
A plugin that abstracts fitness and health repositories like Apple HealthKit or Google Fit.
This work is based on cordova plugin googlefit and on cordova healthkit plugin
For an introduction about Google Fit versus HealthKit see this very good article.
This plugin is kept up to date and requires a recent version of cordova (6 and on) as well as recent iOS and Android SDKs.
If you have any question or small issue, please use the gitter channel.
Google discourages from using Google Fit for medical apps. See the official terms.
In Cordova:
cordova plugin add cordova-plugin-health --variable HEALTH_READ_PERMISSION='App needs read access' --variable HEALTH_WRITE_PERMISSION='App needs write access'
HEALTH_READ_PERMISSION
and HEALTH_WRITE_PERMISSION
are shown when the app tries to grant access to data in HealthKit.
Phonegap Build config.xml
:
<!-- Health plugin -->
<plugin name="cordova-plugin-health" source="npm">
<variable name="HEALTH_READ_PERMISSION" value="App needs read access"/>
<variable name="HEALTH_WRITE_PERMISSION" value="App needs write access"/>
</plugin>
<!-- Only if iOS -->
<!-- Read access -->
<config-file platform="ios" parent="NSHealthShareUsageDescription">
<string>App needs read access</string>
</config-file>
<!-- Write access -->
<config-file platform="ios" parent="NSHealthUpdateUsageDescription">
<string>App needs write access</string>
</config-file>
If, for some reason, the Info.plist loses the HEALTH_READ_PERMISSION and HEALTH_WRITE_PERMISSION, you probably need to add the following to your project's package.json:
{
"cordova": {
"plugins": {
"cordova-plugin-health": {
"HEALTH_READ_PERMISSION": "App needs read access",
"HEALTH_WRITE_PERMISSION": "App needs write access"
},
},
}
}
This is known to happen when using the Ionic Package cloud service.
NSHealthShareUsageDescription
and NSHealthUpdateUsageDescription
. These are assigned with a default string by the plugin, but you may want to contextualise them for your app.keytool -list -printcert -jarfile yourapp.apk
.<framework src="com.google.android.gms:play-services-fitness:+" />
). This is done to likely guarantee the compatibility with other plugins using Google Play Services, but bear in mind that a) the plugin was tested until version 9.8.0 of the APIs and b) other plugins may be using a different version of the API. If you run into an issue, check the generated gradle file (build.gradle) under dependencies
between // SUB-PROJECT DEPENDENCIES START
and // SUB-PROJECT DEPENDENCIES END
and make sure that all versions of the com.google.android.gms:play-services-xxxx
are the same.As HealthKit does not allow adding custom data types, only a subset of data types supported by HealthKit has been chosen. Google Fit is limited to fitness data and, for health, custom data types are defined with the suffix of the package name of your project.
Data type | Unit | HealthKit equivalent | Google Fit equivalent |
---|---|---|---|
steps | count | HKQuantityTypeIdentifierStepCount | TYPE_STEP_COUNT_DELTA |
distance | m | HKQuantityTypeIdentifierDistanceWalkingRunning + HKQuantityTypeIdentifierDistanceCycling | TYPE_DISTANCE_DELTA |
appleExerciseTime | min | HKQuantityTypeIdentifierAppleExerciseTime | NA |
calories | kcal | HKQuantityTypeIdentifierActiveEnergyBurned + HKQuantityTypeIdentifierBasalEnergyBurned | TYPE_CALORIES_EXPENDED |
calories.active | kcal | HKQuantityTypeIdentifierActiveEnergyBurned | TYPE_CALORIES_EXPENDED - (TYPE_BASAL_METABOLIC_RATE * time window) |
calories.basal | kcal | HKQuantityTypeIdentifierBasalEnergyBurned | TYPE_BASAL_METABOLIC_RATE * time window |
activity | activityType | HKWorkoutTypeIdentifier + HKCategoryTypeIdentifierSleepAnalysis | TYPE_ACTIVITY_SEGMENT |
height | m | HKQuantityTypeIdentifierHeight | TYPE_HEIGHT |
weight | kg | HKQuantityTypeIdentifierBodyMass | TYPE_WEIGHT |
heart_rate | count/min | HKQuantityTypeIdentifierHeartRate | TYPE_HEART_RATE_BPM |
fat_percentage | % | HKQuantityTypeIdentifierBodyFatPercentage | TYPE_BODY_FAT_PERCENTAGE |
blood_glucose | mmol/L | HKQuantityTypeIdentifierBloodGlucose | TYPE_BLOOD_GLUCOSE |
insulin | IU | HKQuantityTypeIdentifierInsulinDelivery | NA |
gender | HKCharacteristicTypeIdentifierBiologicalSex | custom (YOUR_PACKAGE_NAME.gender) | |
date_of_birth | HKCharacteristicTypeIdentifierDateOfBirth | custom (YOUR_PACKAGE_NAME.date_of_birth) | |
nutrition | HKCorrelationTypeIdentifierFood | TYPE_NUTRITION | |
nutrition.calories | kcal | HKQuantityTypeIdentifierDietaryEnergyConsumed | TYPE_NUTRITION, NUTRIENT_CALORIES |
nutrition.fat.total | g | HKQuantityTypeIdentifierDietaryFatTotal | TYPE_NUTRITION, NUTRIENT_TOTAL_FAT |
nutrition.fat.saturated | g | HKQuantityTypeIdentifierDietaryFatSaturated | TYPE_NUTRITION, NUTRIENT_SATURATED_FAT |
nutrition.fat.unsaturated | g | NA | TYPE_NUTRITION, NUTRIENT_UNSATURATED_FAT |
nutrition.fat.polyunsaturated | g | HKQuantityTypeIdentifierDietaryFatPolyunsaturated | TYPE_NUTRITION, NUTRIENT_POLYUNSATURATED_FAT |
nutrition.fat.monounsaturated | g | HKQuantityTypeIdentifierDietaryFatMonounsaturated | TYPE_NUTRITION, NUTRIENT_MONOUNSATURATED_FAT |
nutrition.fat.trans | g | NA | TYPE_NUTRITION, NUTRIENT_TRANS_FAT (g) |
nutrition.cholesterol | mg | HKQuantityTypeIdentifierDietaryCholesterol | TYPE_NUTRITION, NUTRIENT_CHOLESTEROL |
nutrition.sodium | mg | HKQuantityTypeIdentifierDietarySodium | TYPE_NUTRITION, NUTRIENT_SODIUM |
nutrition.potassium | mg | HKQuantityTypeIdentifierDietaryPotassium | TYPE_NUTRITION, NUTRIENT_POTASSIUM |
nutrition.carbs.total | g | HKQuantityTypeIdentifierDietaryCarbohydrates | TYPE_NUTRITION, NUTRIENT_TOTAL_CARBS |
nutrition.dietary_fiber | g | HKQuantityTypeIdentifierDietaryFiber | TYPE_NUTRITION, NUTRIENT_DIETARY_FIBER |
nutrition.sugar | g | HKQuantityTypeIdentifierDietarySugar | TYPE_NUTRITION, NUTRIENT_SUGAR |
nutrition.protein | g | HKQuantityTypeIdentifierDietaryProtein | TYPE_NUTRITION, NUTRIENT_PROTEIN |
nutrition.vitamin_a | mcg (HK), IU (GF) | HKQuantityTypeIdentifierDietaryVitaminA | TYPE_NUTRITION, NUTRIENT_VITAMIN_A |
nutrition.vitamin_c | mg | HKQuantityTypeIdentifierDietaryVitaminC | TYPE_NUTRITION, NUTRIENT_VITAMIN_C |
nutrition.calcium | mg | HKQuantityTypeIdentifierDietaryCalcium | TYPE_NUTRITION, NUTRIENT_CALCIUM |
nutrition.iron | mg | HKQuantityTypeIdentifierDietaryIron | TYPE_NUTRITION, NUTRIENT_IRON |
nutrition.water | ml | HKQuantityTypeIdentifierDietaryWater | TYPE_HYDRATION |
nutrition.caffeine | g | HKQuantityTypeIdentifierDietaryCaffeine | NA |
Note: units of measurement are fixed!
Returned objects contain a set of fixed fields:
Example values:
Data type | Value |
---|---|
steps | 34 |
distance | 101.2 |
appleExerciseTime | 24 |
calories | 245.3 |
activity | "walking" Notes: recognized activities and their mappings in Google Fit / HealthKit can be found here the query also returns calories (kcal) and distance (m) |
height | 185.9 |
weight | 83.3 |
heart_rate | 66 |
fat_percentage | 31.2 |
blood_glucose | { glucose: 5.5, meal: 'breakfast', sleep: 'fully_awake', source: 'capillary_blood' } Notes: to convert to mg/dL, multiply by 18.01559 (The molar mass of glucose is 180.1559)meal can be: 'before_meal' (iOS only), 'after_meal' (iOS only), 'fasting', 'breakfast', 'dinner', 'lunch', 'snack', 'unknown', 'before_breakfast', 'before_dinner', 'before_lunch', 'before_snack', 'after_breakfast', 'after_dinner', 'after_lunch', 'after_snack'sleep can be: 'fully_awake', 'before_sleep', 'on_waking', 'during_sleep'source can be: 'capillary_blood' ,'interstitial_fluid', 'plasma', 'serum', 'tears', whole_blood' |
insulin | { insulin: 2.3, reason: 'bolus' } Notes: Insulin is currently only available on iOS reason can be 'bolus' or 'basal' |
gender | "male" |
date_of_birth | { day: 3, month: 12, year: 1978 } |
nutrition | { item: "cheese", meal_type: "lunch", brand_name: "McDonald's", nutrients: { nutrition.fat.saturated: 11.5, nutrition.calories: 233.1 } } Note: the brand_name property is only available on iOS |
nutrition.X | 12.4 |
Tells if either Google Fit or HealthKit are available.
navigator.health.isAvailable(successCallback, errorCallback)
Checks if recent Google Play Services and Google Fit are installed. If the play services are not installed, or are obsolete, it will show a pop-up suggesting to download them. If Google Fit is not installed, it will open the Play Store at the location of the Google Fit app. The plugin does not wait until the missing packages are installed, it will return immediately. If both Play Services and Google Fit are available, this function just returns without any visible effect.
This function is only available on Android.
navigator.health.promptInstallFit(successCallback, errorCallback)
Requests read and write access to a set of data types. It is recommendable to always explain why the app needs access to the data before asking the user to authorize it.
Important: this method must be called before using the query and store methods, even if the authorization has already been given at some point in the past. Failure to do so may cause your app to crash, or in the case of Android, Google Fit may not be ready.
navigator.health.requestAuthorization(datatypes, successCallback, errorCallback)
[
'calories', 'distance', // Read and write permissions
{
read : ['steps'], // Read only permission
write : ['height', 'weight'] // Write only permission
}
]
activity
also includes sleep. If you want to get authorization only for workouts, you can specify workouts
as datatype, but be aware that this is only availabe in iOS.Check if the app has authorization to read/write a set of datatypes.
navigator.health.isAuthorized(datatypes, successCallback, errorCallback)
Removes authorization from the app. Works only on Android.
navigator.health.disconnect(successCallback, errorCallback)
Gets all the data points of a certain data type within a certain time window.
Warning: if the time span is big, it can generate long arrays!
navigator.health.query({
startDate: new Date(new Date().getTime() - 3 * 24 * 60 * 60 * 1000), // three days ago
endDate: new Date(), // now
dataType: 'height'
}, successCallback, errorCallback)
limit: xxx
to your query object.ascending: true
to your query object.workouts
datatype, but be aware that this will only be availabe in iOS.filtered: true
.Gets aggregated data in a certain time window. Usually the sum is returned for the given quantity.
navigator.health.queryAggregated({
startDate: new Date(new Date().getTime() - 3 * 24 * 60 * 60 * 1000), // three days ago
endDate: new Date(), // now
dataType: 'steps',
bucket: 'day'
}, successCallback, errorCallback)
Not all data types are supported for aggregated queries. The following table shows what types are supported and examples of the returned object:
Data type | Example of returned object |
---|---|
steps | { startDate: Date, endDate: Date, value: 5780, unit: 'count' } |
distance | { startDate: Date, endDate: Date, value: 12500.0, unit: 'm' } |
calories | { startDate: Date, endDate: Date, value: 25698.1, unit: 'kcal' } |
calories.active | { startDate: Date, endDate: Date, value: 3547.4, unit: 'kcal' } |
calories.basal | { startDate: Date, endDate: Date, value: 13146.1, unit: 'kcal' } |
activity | { startDate: Date, endDate: Date, value: { still: { duration: 520000, calories: 30, distance: 0 }, walking: { duration: 223000, calories: 20, distance: 15 }}, unit: 'activitySummary' } Note: duration is expressed in milliseconds, distance in meters and calories in kcal |
nutrition | { startDate: Date, endDate: Date, value: { nutrition.fat.saturated: 11.5, nutrition.calories: 233.1 }, unit: 'nutrition' } Note: units of measurement for nutrients are fixed according to the table at the beginning of this README |
nutrition.x | { startDate: Date, endDate: Date, value: 23, unit: 'mg'} |
filtered: true
to the query object. This returns the steps as filtered out by Google Fit, or the non-manual ones from HealthKit.Stores a data point.
navigator.health.store({
startDate: new Date(new Date().getTime() - 3 * 60 * 1000), // three minutes ago
endDate: new Date(),
dataType: 'steps',
value: 180,
sourceName: 'my_app',
sourceBundleId: 'com.example.my_app'
}, successCallback, errorCallback)
dataType: 'activity', value: 'walking', calories: 20, distance: 520
. Be aware, though, that you need permission to write calories and distance first, or the call will fail.cycling: true
.Deletes a range of data points.
navigator.health.delete({
startDate: new Date(new Date().getTime() - 3 * 60 * 1000), // three minutes ago
endDate: new Date(),
dataType: 'steps'
}, successCallback, errorCallback)
cycling: true
.unit
attribute, you can find the comprehensive list of possible units from the Apple Developers documentation.Short term:
Long term:
Any help is more than welcome!
I don't know Objective C and I am not interested in learning it now, so I would particularly appreciate someone who could give me a hand with the iOS part. Also, I would love to know from you if the plugin is currently used in any app actually available online. Just send me an email to my_username at gmail.com. For donations, you can use my monzo.me account.
Thanks!
FAQs
A plugin that abstracts fitness and health repositories like Apple HealthKit or Google Fit
We found that cordova-plugin-mhw-healthk demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket’s new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.
Research
/Security News
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.
Security News
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.