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:
- Open the Android SDK Manager.
- Under SDK Tools, find Google Play services.
- 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)
- When you create your bundleId, check the healthkit box
- Add Privacy - Health Share Usage Description to your Xcode project
- Add Privacy - Health Update Usage Description to your Xcode project
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 ofHealthFitData
with all datapoints - otherwise (type is
HealthFitResultType.SUM
), the data key isHealthFitData
object
- whether type is
- 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
withHealthFitResultType.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
withHealthFitResultType.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:
- go to your Google account
- go to "data é privacy" sub menu
- scroll down to "info you can share with others" and select "profile"
- update visibility to "anyone" for your gender and birthday
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, theNOT_AVAILABLE
error is thrown - The maximum timeinterval for
HealthFitDataType.MINDFUL
is 2419200 seconds. Beyond this limit, theNOT_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, theNOT_AVAILABLE
error is thrown - The maximum timeinterval for
HealthFitDataType.MINDFUL
is 2419200 seconds. Beyond this limit, theNOT_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)|