health 1.0.2+2

  • Readme
  • Changelog
  • Example
  • Installing
  • 91

Health #

This library combines both GoogleFit and AppleHealthKit. It support most of the values provided.

Supports iOS and Android X

Data Types #

Data TypeAvailable on iOSAvailable on AndroidComments
BODY_FATyesyes
HEIGHTyesyes
WEIGHTyesyes
BODY_MASS_INDEXyesyes
WAIST_CIRCUMFERENCEyes
STEPSyesyes
BASAL_ENERGY_BURNEDyes
ACTIVE_ENERGY_BURNEDyesyes
HEART_RATEyesyes
BODY_TEMPERATUREyesyes
BLOOD_PRESSURE_SYSTOLICyesyes
BLOOD_PRESSURE_DIASTOLICyesyes
RESTING_HEART_RATEyes
WALKING_HEART_RATEyes
BLOOD_OXYGENyesyes
BLOOD_GLUCOSEyesyes
ELECTRODERMAL_ACTIVITYyesRequires Apple Watch
HIGH_HEART_RATE_EVENTyesRequires Apple Watch
LOW_HEART_RATE_EVENTyesRequires Apple Watch
IRREGULAR_HEART_RATE_EVENTyesRequires Apple Watch

Setup #

Apple HealthKit (iOS) #

Step 1: Append the Info.plist with the following 2 entries

<key>NSHealthShareUsageDescription</key>
<string>We will sync your data with the Apple Health app to give you better insights</string>
<key>NSHealthUpdateUsageDescription</key>
<string>We will sync your data with the Apple Health app to give you better insights</string>

Step 2: Enable "HealthKit" inside the "Capabilities" tab.

Google Fit (Android) #

Follow the guide at https://developers.google.com/fit/android/get-api-key

Below is an example of following the guide:

Change directory to your key-store directory (MacOS): cd ~/.android/

Get your keystore SHA1 fingerprint: keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

Example output:

Alias name: androiddebugkey
Creation date: Jan 01, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 4aa9b300
Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033
Certificate fingerprints:
     MD5:  AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:F9
     SHA1: BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75
     Signature algorithm name: SHA1withRSA
     Version: 3

Follow the instructions at https://console.developers.google.com/flows/enableapi?apiid=fitness for setting up an OAuth2 Client ID for a Google project, and adding the SHA1 fingerprint to that OAuth2 credential.

The client id will look something like YOUR_CLIENT_ID.apps.googleusercontent.com

Android X #

Replace the content of the android/gradle.properties file with the following lines:

org.gradle.jvmargs=-Xmx1536M
android.enableJetifier=true
android.useAndroidX=true

Usage #

Below is a snippet from the example app showing the plugin in use.

Health data #

A HealthData object contains the following fields:

num value;
String unit;
int dateFrom;
int dateTo;
String dataType;
String platform;

A HealthData healthData object can be serialized to JSON with the healthData.toJson() method.

Check authorization #

The following example shows prompting the user for authorization to the API, which is necessary in order to fetch any data.

Calls to fetch data from the API should be done within the inner if-clause.

Future.delayed(Duration(seconds: 2), () async {
    bool _isAuthorized = await Health.requestAuthorization();
    if (_isAuthorized) {
    /// Do something with the API here
    }
});

Specify data type #

Data types indicate the type of data to fetch from the API and are available from the enum class HealthDataType.

Below is an example of a few data types:

List<HealthDataType> types = [
        HealthDataType.WEIGHT,
        HealthDataType.HEIGHT,
        HealthDataType.STEPS,
    ];

For an overview of all data types see the table in Data Types section above.

Check if data type available #

Not all data types are available on both platforms. In order to check whether or not a data type is available for the current platform,

bool weightAvailable = Health.isDataTypeAvailable(HealthDataType.WEIGHT);

Fetch data for a given type #

Given the list of data types (types) as well as a startData and an endDate, we can now fetch all the data, for each data type with a call to the Health.getHealthDataFromType function.

Set up dates:

DateTime startDate = DateTime.utc(2001, 01, 01);
DateTime endDate = DateTime.now();

Make the fetch call:

List<HealthDataPoint> healthDataList = List<HealthDataPoint>();

for (HealthDataType type in types) {
    /// Calls to 'Health.getHealthDataFromType' must be wrapped in a try catch block.
    try {
        List<HealthDataPoint> healthData = await Health.getHealthDataFromType(startDate, endDate, type);
        healthDataList.addAll(healthData);
    } catch (exception) {
        print(exception.toString());
    }
}

This call must be inside a try catch block, since when some data type is not available, an exception will be thrown. Also, make sure the access to the API has been authorized (see Check authorization).

Full example #

void _getHealthDataPoints() async {

    List<HealthDataType> types = [
        HealthDataType.WEIGHT,
        HealthDataType.HEIGHT,
        HealthDataType.STEPS,
    ];

    DateTime startDate = DateTime.utc(2001, 01, 01);
    DateTime endDate = DateTime.now();

    List<HealthDataPoint> healthDataList = List<HealthDataPoint>();

    Future.delayed(Duration(seconds: 2), () async {
        bool isAuthorized = await Health.requestAuthorization();
        if (isAuthorized) {
            for (HealthDataType type in types) {
                /// Calls to 'Health.getHealthDataFromType' must be wrapped in a try catch block.
                try {
                    List<HealthDataPoint> healthData = await Health.getHealthDataFromType(startDate, endDate, type);
                    healthDataList.addAll(healthData);
                } catch (exception) {
                    print(exception.toString());
                }
            }
        }
        /// Do something with the health data list
        for (var healthData in healthDataList) {
            print(healthData);
        }
    });
}

1.0.2 #

  • Updated documentation for Android and Google Fit.

1.0.1 #

  • Streamlined DataType units in Flutter.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:health/health.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var _healthKitOutput;
  var _healthDataList = List<HealthDataPoint>();
  bool _isAuthorized = false;

  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    DateTime startDate = DateTime.utc(2001, 01, 01);
    DateTime endDate = DateTime.now();

    Future.delayed(Duration(seconds: 2), () async {
      _isAuthorized = await Health.requestAuthorization();

      if (_isAuthorized) {
        print('Authorized');

        bool weightAvailable =
            Health.isDataTypeAvailable(HealthDataType.WEIGHT);
        print("is WEIGHT data type available?: $weightAvailable");

        /// Specify the wished data types
        List<HealthDataType> types = [
          HealthDataType.WEIGHT,
          HealthDataType.HEIGHT,
          HealthDataType.STEPS,
          HealthDataType.BODY_MASS_INDEX,
          HealthDataType.WAIST_CIRCUMFERENCE,
          HealthDataType.BODY_FAT_PERCENTAGE,
          HealthDataType.ACTIVE_ENERGY_BURNED,
          HealthDataType.BASAL_ENERGY_BURNED,
          HealthDataType.HEART_RATE,
          HealthDataType.BLOOD_PRESSURE_SYSTOLIC,
          HealthDataType.BLOOD_PRESSURE_DIASTOLIC,
          HealthDataType.RESTING_HEART_RATE,
          HealthDataType.BLOOD_GLUCOSE,
          HealthDataType.BLOOD_OXYGEN,
        ];

        for (HealthDataType type in types) {
          /// Calls to 'Health.getHealthDataFromType'
          /// must be wrapped in a try catch block.b
          try {
            List<HealthDataPoint> healthData =
                await Health.getHealthDataFromType(startDate, endDate, type);
            _healthDataList.addAll(healthData);
          } catch (exception) {
            print(exception.toString());
          }
        }

        /// Print the results
        for (var x in _healthDataList) {
          print("Data point: $x");
        }

        /// Update the UI to display the results
        setState(() {});
      } else {
        print('Not authorized');
      }
    });

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.sync),
              onPressed: () {
                initPlatformState();
              },
            )
          ],
        ),
        body: _healthDataList.isEmpty
            ? Text('$_healthKitOutput\n')
            : ListView.builder(
                itemCount: _healthDataList.length,
                itemBuilder: (_, index) => ListTile(
                      title: Text(
                          "${_healthDataList[index].dataType.toString()}: ${_healthDataList[index].value.toString()}"),
                      trailing: Text('${_healthDataList[index].unit}'),
                      subtitle: Text(
                          '${DateTime.fromMillisecondsSinceEpoch(_healthDataList[index].dateFrom)} - ${DateTime.fromMillisecondsSinceEpoch(_healthDataList[index].dateTo)}'),
                    )),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  health: ^1.0.2+2

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:health/health.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
82
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
91
Learn more about scoring.

We analyzed this package on Jul 2, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.13
  • Flutter: 1.17.5

Analysis suggestions

Package does not support Flutter platform linux

Because of import path [package:health/health.dart] that declares support for platforms: android, ios

Package does not support Flutter platform macos

Because of import path [package:health/health.dart] that declares support for platforms: android, ios

Package does not support Flutter platform web

Because of import path [package:health/health.dart] that declares support for platforms: android, ios

Package does not support Flutter platform windows

Because of import path [package:health/health.dart] that declares support for platforms: android, ios

Package not compatible with SDK dart

because of import path [health] that is in a package requiring null.

Health suggestions

Format lib/health.dart.

Run flutter format to format lib/health.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8
Dev dependencies
flutter_test