0.0.11 • Published 2 years ago

capacitor-health-fit v0.0.11

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

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 nameiOSAndroid
WEIGHTHKQuantityTypeIdentifier.bodyMass
STEP_COUNTHKQuantityTypeIdentifier.stepCount
ACTIVITYHKQuantityTypeIdentifier.appleExerciseTime
MINDFULHKCategoryTypeIdentifierMindfulSession
GENERAL_INFORMATIONHKCharacteristicTypeIdentifier.biologicalSex & HKCharacteristicTypeIdentifier.dateOfBirth & HKCharacteristicTypeIdentifier.bloodType

Samples types

Samples avaivables in the plugin (list in HealthFitDataType enum)

Sample name for queryunitiOSAndroid
WEIGHTkilogramsHKQuantityTypeIdentifier.bodyMass
STEP_COUNTstepsHKQuantityTypeIdentifier.stepCount
ACTIVITYminutesHKQuantityTypeIdentifier.appleExerciseTime
MINDFULminutesHKCategoryTypeIdentifierMindfulSession

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

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 codesMeaning
HEALTH_FIT_NOT_AVAILABLEHealthkit or Googlefit is not available on the device
MISSING_PLUGIN_PARAMETERA required parameter is missing
BAD_PLUGIN_PARAMETERInvalid parameter passed to the plugin (data type problem)
UNKNOWN_TYPEThe datatype parameter is not recognized (it is not part of HealthFitDataType)
AUTHORIZATION_NOT_DETERMINEDThe authorization for a datatype is not determined.
PERMISSION_DENIEDAccess or write permission to a datatype is denied
TECHNICAL_ERRORUnrecognized and unanticipated error. Details are available in the logs
BAD_DATE_FORMATWrong date format
BAD_END_DATEThe end date is earlier than the start date (when retrieving or inserting data)
NOT_AVAILABLEAction not available (for example, add an activity on iOS)
0.0.11

2 years ago

0.0.10

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.5

4 years ago

0.0.6

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.4

4 years ago

0.0.1

4 years ago