npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

capacitor-health-fit

v0.0.11

Published

Capacitor plugin that allows to communicate with Healthkit and Google fit

Downloads

28

Readme

Capacitor health

About this plugin

This capacitor plugin allows you to communicate with healthkit or Google fit SDK.

  • Android and iOS support.
  • Open health app (iOS only)
  • Request authorizations
  • Check authorizations
  • Get data
  • Add data
  • Delete data

Getting started

Installation

npm install capacitor-health-fit
npx cap sync ios|android

Android Configuration

Before you start to build your app, complete the steps in the following sections.

Get / Create a Google Account

To use the Google Fit APIs, you need a Google Account. You can create a new account or use an existing account. You might want to create a separate account to test your app from a user's perspective.

Set Google play services

Get the latest client library for Google Play services on your development host:

  1. Open the Android SDK Manager.
  2. Under SDK Tools, find Google Play services.
  3. If the status for these packages isn't Installed, select them both and click Install Packages.

Get an OAuth 2.0 client ID

To enable the Fitness API, you need an OAuth 2.0 client ID.

Follow steps in Google Guide

Create and configure your project

We recommend using the Android Studio development environment to build an app with the Fitness API. For details on how to make a new project and configure it in Android Studio, see Create a project.

iOS Configuration

  • Add HealthKit to your Xcode project (section signing & capabilities)

Alt text

  • When you create your bundleId, check the healthkit box

Alt text

  • Add Privacy - Health Share Usage Description to your Xcode project
  • Add Privacy - Health Update Usage Description to your Xcode project

Alt text

Basic usage

import {Plugins} from '@capacitor/core';
const {HealthFit} = Plugins;

...

HealthFit.getGeneralInformations()
.then(data => {
    console.debug('Data received:', JSON.stringify(data));
})
.catch(e => alert(e));

API

Authorization types

Authorization types in the plugin (list in HealthFitAuthorizationDataType enum)

|Authorization name | iOS | Android | |---|---|---| |WEIGHT|HKQuantityTypeIdentifier.bodyMass|| |STEP_COUNT|HKQuantityTypeIdentifier.stepCount|| |ACTIVITY|HKQuantityTypeIdentifier.appleExerciseTime|| |MINDFUL|HKCategoryTypeIdentifierMindfulSession|| |GENERAL_INFORMATION|HKCharacteristicTypeIdentifier.biologicalSex & HKCharacteristicTypeIdentifier.dateOfBirth & HKCharacteristicTypeIdentifier.bloodType||

Samples types

Samples avaivables in the plugin (list in HealthFitDataType enum)

|Sample name for query | unit | iOS | Android | |---|---|---|---| |WEIGHT|kilograms|HKQuantityTypeIdentifier.bodyMass| |STEP_COUNT|steps|HKQuantityTypeIdentifier.stepCount| |ACTIVITY|minutes|HKQuantityTypeIdentifier.appleExerciseTime| |MINDFUL|minutes|HKCategoryTypeIdentifierMindfulSession|

Android quirks

ACTIVITY represent move in minutes date return by Fit api

Types

// Gender enum returned by getGeneralInformation method
export enum Gender {
  notSet,
  female ,
  male,
  other
}

// Blood type enum returned by getGeneralInformation method
export enum BloodType {
  notSet,
  aPositive,
  aNegative,
  bPositive,
  bNegative ,
  abPositive,
  abNegative,
  oPositive,
  oNegative
}

// Return type of getGeneralInformation
export interface UserGeneralData {
  data: {
    birthday: Date,
    bloodType?: BloodType, // BloodType only available on iOS
    gender: Gender,
  }
}

// List of all permissions that can be requested in the plugin
export enum HealthFitAuthorizationDataType {
  WEIGHT = 'WEIGHT',
  STEP_COUNT = 'STEP_COUNT',
  ACTIVITY = 'ACTIVITY',
  MINDFUL = 'MINDFUL',
  GENERAL_INFORMATION = 'GENERAL_INFORMATION'
}

// List of all data types managed by the plugin
export enum HealthDataType {
  WEIGHT = 'WEIGHT',
  STEP_COUNT = 'STEP_COUNT',
  ACTIVITY = 'ACTIVITY',
  MINDFUL = 'MINDFUL',
}

// Possible return type when calling the read() or readMultiple() methods
// SUM of the WEIGHT is a forbidden action (this data does not make sense)
export enum HealthFitResultType {
  ALL = 'ALL', // Returns a list with the details of all the data
  SUM = 'SUM' // Returns an object with the sum of the data (example, the total number of steps over 1 day)
}

// Possible permission type when calling requestAuthorization
export enum HealthFitAuthorizationType {
  READ =  'READ',
  WRITE = 'WRITE'
}

// Return type for the read method
export interface HealthFitHistory {
  data: HealthFitData[] | HealthFitData | {}; // "ALL" option return an Array, "SUM" option return the object or an empty one if no data.
}

// Return type for the readMultiple method
export type HealthFitMultipleHistory = {
  [type in HealthFitDataType]: HealthFitData[] & HealthFitError[] | HealthFitData & HealthFitError | {}
}

// Detail of a data retrieved from health stores
export type HealthFitData = {
  start: string, // 2021-11-16T10:34:35.973Z format
  end: string, // 2021-11-16T10:34:35.973Z format 
  value?: number, // value is only optional for HealthFitDataType.MINDFUL
  unit: string,
  source?: string, // source available for a unique sample, but not for the sum of multiple samples
};

// Structure of error handling
export type HealthFitError = {
  succeeded: boolean,
  code?: string,
  message?: string
}

Functions

isAvailable()

Tells if HealthKit or Google fit is available on the device.

isAvailable(): Promise<{ available: boolean }>;
  • successCallback: {type: function(available)}, available if true is passed, otherwise false

Android quirks

Google Fit is only available on sdk version upper to 24 (included)

openHealth()

Open health app (iOS only)

openHealth(): void;

disconnect()

Disconnect user and app from GoogleFit

disconnect(): Promise<void>;

iOS quirks

  • This method is not needed and does nothing on iOS.

isAuthorized()

Tells if the application has read and/or write permission for a datatype

isAuthorized(options : {type: String, mode: HealthFitAuthorizationType}): Promise<{authorized: boolean}>;
  • successCallback: {type: function(authorized)}, authorized if true is passed, otherwise false
  • errorCallback: {type: function(err)}, called if something went wrong, err can be :
    • NOT_AVAILABLE
    • MISSING_PLUGIN_PARAMETER: when a parameter is missing
    • : when an unknown authorization type is passed

iOS quirks

  • This method will only work with the HealthFitAuthorizationType.WRITE parameter and will only check the write permission. Read-only data authorization status can't be checked. This is an intended behaviour of HealthKit.

requestAuthorization()

Opens a page with the requested permissions (iOS) or a pop-up (Android), allows the user to allow or deny read or write access to one or more data.

requestAuthorization(options: { read: Array<string>; write: Array<string>; }): Promise<void>;
  • errorCallback: {type: function(err)}, called if something went wrong, err can be :
    • HEALTH_FIT_NOT_AVAILABLE
    • MISSING_PLUGIN_PARAMETER
    • NOT_AVAILABLE (Only for WRITE on ACTIVITY on iOS)

iOS quirks

  • On iOS, it is not possible to write an activity (HealthFitDataType.ACTIVITY). It is therefore not possible to request a write authorization on this type of data.

Android quirks

  • Please take a look at this document which explains how permissions should be requested on Android. https://developer.android.com/training/permissions/requesting

read()

Gets all the data points of a certain datatype within a certain time window.

read(options: {type: string, start: Date, end: Date, result: string}): Promise<HealthFitHistory>;
  • successCallback: {type: function(HealthFitHistory)} :
    • whether type is HealthFitResultType.ALL, the data key is a list of HealthFitData with all datapoints
    • otherwise (type is HealthFitResultType.SUM), the data key is HealthFitData object
  • errorCallback: {type: function(err)}, called if something went wrong, err can be :
    • AUTHORIZATION_NOT_DETERMINED
    • BAD_DATE_FORMAT
    • BAD_END_DATE
    • HEALTH_FIT_NOT_AVAILABLE: iOS only
    • MISSING_PLUGIN_PARAMETER
    • UNKNOWN_TYPE
    • TECHNICAL_ERROR
    • NOT_AVAILABLE (only in iOS for HealthFitDataType.WEIGHT with HealthFitResultType.SUM)

Android quirks

Start and end dates in the HealthFitData response type matched with the real data found on GoogleFit Api inside the requested interval. Request interval is exclusive. For example for an activity between 09:00 and 10:00, querying this exact interval will not return activity minutes, but 08:59 and 10:01 will.

readMultiple()

Gets all the data points of multiple datatype within a certain datetime interval.

readMultiple(options: {types: Array<string>, start: Date, end: Date}): Promise<HealthFitMultipleHistory>;
  • successCallback: {type: function(HealthFitMultipleHistory)} :
    • Object containing each datatype with all associated values. Each object keys is associated with a datatype requested.
  • errorCallback: {type: function(err)}, called if something went wrong, err can be :
    • AUTHORIZATION_NOT_DETERMINED
    • BAD_DATE_FORMAT
    • BAD_END_DATE
    • HEALTH_FIT_NOT_AVAILABLE: iOS only
    • MISSING_PLUGIN_PARAMETER
    • UNKNOWN_TYPE
    • TECHNICAL_ERROR
    • NOT_AVAILABLE (only for HealthFitDataType.BODY_MASS with HealthFitResultType.SUM)
    • BAD_PLUGIN_PARAMETER (If the data passed is not an array of HealthFitDataType)

Android quirks

Start and end dates in the HealthFitData response type matched with the real data found on GoogleFit Api inside the requested interval. Request interval is exclusive. For example for an activity between 09:00 and 10:00, querying this exact interval will not return activity minutes, but 08:59 and 10:01 will.

getGeneralInformation()

Allows to retrieve the user's date of birth, gender and blood type

getGeneralInformation(): Promise<UserGeneralData>;
  • successCallback: : {type: function(UserGeneralData)} : Object containing data. blood type and gender are enumerations (BloodType, Gender).
  • errorCallback: {type: function(err)}, called if something went wrong, err can be :
    • HEALTH_FIT_NOT_AVAILABLE: iOS only
    • TECHNICAL_ERROR

Android quirks

Response

On Android, response object contain only birthday and gender. It's not possible to get bloodtype as it's not an available data.

Restriction and visibility

Only public data can be retrieved.

Default visibility about gender and birthday is private. To change the visibility, follow theses steps:

  1. go to your Google account
  2. go to "data é privacy" sub menu
  3. scroll down to "info you can share with others" and select "profile"
  4. update visibility to "anyone" for your gender and birthday

Android Data and privacy

insert()

Insert a data of a certain datatype within a certain time window.

insert(options: {type: string, value?: string, start?: Date, end?: Date}): Promise<{succeeded: boolean}>; // value is only optional for HealthFitDataType.MINDFUL
  • successCallback: {type: function(success)} : Returns true if data added successfully, otherwise returns false
  • errorCallback: {type: function(err)}, called if something went wrong, err can be :
    • BAD_END_DATE
    • BAD_DATE_FORMAT
    • HEALTH_FIT_NOT_AVAILABLE: iOS only
    • MISSING_PLUGIN_PARAMETER
    • UNKNOWN_TYPE
    • NOT_AVAILABLE (only for HealthFitDataType.ACTIVITY on iOS)

iOS quirks

  • It is not possible to insert HealthFitDataType.ACTIVITY data
  • The maximum timeinterval for HealthFitDataType.BODY_MASS data is 345600 seconds. Beyond this limit, the NOT_AVAILABLE error is thrown
  • The maximum timeinterval for HealthFitDataType.MINDFUL is 2419200 seconds. Beyond this limit, the NOT_AVAILABLE error is thrown

Android quirks

Be sure to insert data into a free datetime interval. Whether the inserted pediod is:

  • included into another existing period, the new one will be hidden.
  • started or ended outside another existing period, Google will split the new one and eval new data with a linear function.

insertMultiple()

Insert multiple data of multiple datatype within a certain time window.

  • if no start & end datetime parameter, start & end will equal to NOW on iOS and now minus one hour for Android,
  • if no end parameter, end = start,
  • if no end parameter, but no start parameter, MISSING_PLUGIN_PARAMETER exception is called.
insertMultiple(options: {list: Array<{ type: string; value: string, start?: Date, end?: Date }>}): Promise<{data: Array<HealthFitError & { index: number }>}>;
  • successCallback: {type: function(Array<{success: boolean, error?: string})} : Returns a list containing the response to each insert (success or error, with reason for the error). An index is available and corresponds to the index of the input array.
  • errorCallback: {type: function(err)}, called if something went wrong, err can be :
    • BAD_END_DATE
    • BAD_DATE_FORMAT
    • HEALTH_FIT_NOT_AVAILABLE: iOS only
    • MISSING_PLUGIN_PARAMETER
    • UNKNOWN_TYPE
    • NOT_AVAILABLE (only for HealthFitDataType.ACTIVITY on iOS)
    • BAD_PLUGIN_PARAMETER (If the data passed is not an array of HealthFitDataType)

iOS quirks

  • It is not possible to insert HealthFitDataType.ACTIVITY data
  • The maximum timeinterval for HealthFitDataType.BODY_MASS data is 345600 seconds. Beyond this limit, the NOT_AVAILABLE error is thrown
  • The maximum timeinterval for HealthFitDataType.MINDFUL is 2419200 seconds. Beyond this limit, the NOT_AVAILABLE error is thrown

Android quirks

Be sure to insert data into a free datetime interval. Whether the inserted pediod is:

  • included into another existing period, the new one will be hidden.
  • started or ended outside another existing period, Google will split the new one and eval new data with a linear function.

When empty start and end datetime are passed, default values are:

  • start: now minus one hour
  • end: now

delete()

Allow user to delete data in a time interval

delete(options: {type: string, start: Date, end: Date}): Promise<{succeeded: boolean}>;
  • successCallback: {type: success} : success if true is passed, otherwise false
  • errorCallback: {type: function(err)}, called if something went wrong, err can be :
    • BAD_END_DATE
    • BAD_DATE_FORMAT
    • HEALTH_FIT_NOT_AVAILABLE: iOS only
    • MISSING_PLUGIN_PARAMETER
    • UNKNOWN_TYPE
    • NOT_AVAILABLE (only for HealthFitDataType.ACTIVITY on iOS)

iOS quirks

  • On iOS, it is not possible to delete HealthFitDataType.ACTIVITY data

Android quirks

  • On Andoid, it's possible to delete HealthFitDataType.ACTIVITY data but it's a non sens. Activity represent the move in minutes, not the real exercice type...

Error management

When plugin error occurs, promise is rejected with a string error code.

try {
  await HealthFit.isAuthorized({
      type: HealthFitDataType.STEP_COUNT,
      mode: HealthFitAuthorizationType.READ
  })
} catch (error) {
  alert(`Error code: ${error}`);
}

Here are available error codes:

|Error codes|Meaning| |---|---| |HEALTH_FIT_NOT_AVAILABLE|Healthkit or Googlefit is not available on the device| |MISSING_PLUGIN_PARAMETER|A required parameter is missing| |BAD_PLUGIN_PARAMETER|Invalid parameter passed to the plugin (data type problem)| |UNKNOWN_TYPE|The datatype parameter is not recognized (it is not part of HealthFitDataType)| |AUTHORIZATION_NOT_DETERMINED|The authorization for a datatype is not determined.| |PERMISSION_DENIED|Access or write permission to a datatype is denied| |TECHNICAL_ERROR|Unrecognized and unanticipated error. Details are available in the logs| |BAD_DATE_FORMAT|Wrong date format| |BAD_END_DATE|The end date is earlier than the start date (when retrieving or inserting data)| |NOT_AVAILABLE|Action not available (for example, add an activity on iOS)|