diff --git a/examples/BodyMeasurements/app/app.js b/examples/BodyMeasurements/app/app.js
new file mode 100644
index 0000000000000000000000000000000000000000..7fde17cc7460f81ce5b2b74bb3ee7b57b0b177e6
--- /dev/null
+++ b/examples/BodyMeasurements/app/app.js
@@ -0,0 +1,56 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+import React, { Component } from 'react';
+import {
+ AppRegistry,
+ StyleSheet,
+ Navigator,
+ Text,
+ View
+} from 'react-native';
+
+
+let Dashboard = require('./components/dashboard/dashboard');
+let Weight = require('./components/weight/weight');
+let Height = require('./components/height/height');
+let BodyMassIndex = require('./components/bodyMassIndex/bodyMassIndex');
+let BodyFatPercentage = require('./components/bodyFatPercentage/bodyFatPercentage');
+let LeanBodyMass = require('./components/leanBodyMass/leanBodyMass');
+
+
+class BodyMeasurementsApp extends Component {
+ render() {
+ return (
+
+ );
+ }
+
+ renderScene(route, navigator) {
+ if(route.name == 'Dashboard') {
+ return
+ }
+ if(route.name == 'Weight') {
+ return
+ }
+ if(route.name == 'Height') {
+ return
+ }
+ if(route.name == 'BodyMassIndex') {
+ return
+ }
+ if(route.name == 'BodyFatPercentage') {
+ return
+ }
+ if(route.name == 'LeanBodyMass') {
+ return
+ }
+ }
+}
+
+module.exports = BodyMeasurementsApp;
+export default BodyMeasurementsApp;
diff --git a/examples/BodyMeasurements/app/assets/images/arrow-right.png b/examples/BodyMeasurements/app/assets/images/arrow-right.png
new file mode 100755
index 0000000000000000000000000000000000000000..3d3b577f21fbd604d49b166d41395979b05cac9d
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/arrow-right.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/bmi.png b/examples/BodyMeasurements/app/assets/images/bmi.png
new file mode 100644
index 0000000000000000000000000000000000000000..562966ac36733b57013950dd01367954a338e91d
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/bmi.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/bodyfat.png b/examples/BodyMeasurements/app/assets/images/bodyfat.png
new file mode 100644
index 0000000000000000000000000000000000000000..d1b2a37eb3f8df8b9c08a414b112bc19e706b941
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/bodyfat.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/dumbbell.png b/examples/BodyMeasurements/app/assets/images/dumbbell.png
new file mode 100644
index 0000000000000000000000000000000000000000..f4660f46943b93ab23cd432582d983fb520fec07
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/dumbbell.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/heartbeat.png b/examples/BodyMeasurements/app/assets/images/heartbeat.png
new file mode 100755
index 0000000000000000000000000000000000000000..b724ae73c69d98c595751a4c76ec37bd3031a735
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/heartbeat.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/measuring-tape.png b/examples/BodyMeasurements/app/assets/images/measuring-tape.png
new file mode 100644
index 0000000000000000000000000000000000000000..9151edd8b84e983f23e312e5d8301aa7adcf3768
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/measuring-tape.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/muscle-mass.png b/examples/BodyMeasurements/app/assets/images/muscle-mass.png
new file mode 100644
index 0000000000000000000000000000000000000000..fe14c4b2a8034a96f475dc1a428c649fa859ef0b
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/muscle-mass.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/ruler.png b/examples/BodyMeasurements/app/assets/images/ruler.png
new file mode 100644
index 0000000000000000000000000000000000000000..9239c29d0ced5e00e502bea68e74ad072e9d3606
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/ruler.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/scale.png b/examples/BodyMeasurements/app/assets/images/scale.png
new file mode 100755
index 0000000000000000000000000000000000000000..37f5710ac52f39f948d198c8bc417e40b2f829c8
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/scale.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/scale_purple.png b/examples/BodyMeasurements/app/assets/images/scale_purple.png
new file mode 100755
index 0000000000000000000000000000000000000000..e78ac21bb2ed0f1b4b30fb82d32cbcdedd7ac5a1
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/scale_purple.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/steps.png b/examples/BodyMeasurements/app/assets/images/steps.png
new file mode 100755
index 0000000000000000000000000000000000000000..a32c9940fe139b7d11f60be169ea8614e8139731
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/steps.png differ
diff --git a/examples/BodyMeasurements/app/assets/images/strength.png b/examples/BodyMeasurements/app/assets/images/strength.png
new file mode 100644
index 0000000000000000000000000000000000000000..84f24856180a3fa4216520d8c700210e44098d38
Binary files /dev/null and b/examples/BodyMeasurements/app/assets/images/strength.png differ
diff --git a/examples/BodyMeasurements/app/components/bodyFatPercentage/bodyFatPercentage.js b/examples/BodyMeasurements/app/components/bodyFatPercentage/bodyFatPercentage.js
new file mode 100644
index 0000000000000000000000000000000000000000..68c7c0accb5720297fee0c9123ca8252ccc8ca7c
--- /dev/null
+++ b/examples/BodyMeasurements/app/components/bodyFatPercentage/bodyFatPercentage.js
@@ -0,0 +1,97 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+import React, { Component } from 'react';
+import {
+ Navigator,
+ TouchableOpacity,
+ Text,
+ View
+} from 'react-native';
+
+import styles from '../../styles/styles';
+import BodyStore from '../../stores/body';
+
+
+class BodyFatPercentage extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = this._getStateObject();
+ }
+
+ componentDidMount() {
+ this.unsub = BodyStore.listen(this._onBodyStoreEvent.bind(this));
+ }
+
+ componentWillUnmount() {
+ this.unsub();
+ }
+
+ _onBodyStoreEvent(evt) {
+ this.setState(this._getStateObject())
+ }
+
+ _getStateObject() {
+ return {
+ bodyFatFormatted: BodyStore.GetBodyFatPercentageFormatted(),
+ };
+ }
+
+ render() {
+ return (
+
+ }/>
+ );
+ }
+
+ renderScene(route, navigator) {
+ return (
+
+
+
+ {this.state.bodyFatFormatted}
+
+
+
+
+
+
+
+ );
+ }
+}
+
+var NavigationBarRouteMapper = {
+ LeftButton(route, navigator, index, nextState) {
+ return (
+ {navigator.parentNavigator.pop()}}>
+
+ Back
+
+
+ );
+ },
+ RightButton(route, navigator, index, nextState) {
+ return null;
+ },
+ Title(route, navigator, index, nextState) {
+ return (
+
+
+ Body Fat Percentage
+
+
+ );
+ }
+};
+
+
+module.exports = BodyFatPercentage;
+export default BodyFatPercentage;
diff --git a/examples/BodyMeasurements/app/components/bodyMassIndex/bodyMassIndex.js b/examples/BodyMeasurements/app/components/bodyMassIndex/bodyMassIndex.js
new file mode 100644
index 0000000000000000000000000000000000000000..0c862f9af6a4ed19634f0f68779818743e2c9f8c
--- /dev/null
+++ b/examples/BodyMeasurements/app/components/bodyMassIndex/bodyMassIndex.js
@@ -0,0 +1,97 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+import React, { Component } from 'react';
+import {
+ Navigator,
+ TouchableOpacity,
+ Text,
+ View
+} from 'react-native';
+
+import styles from '../../styles/styles';
+import BodyStore from '../../stores/body';
+
+
+class BodyMassIndex extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = this._getStateObject();
+ }
+
+ componentDidMount() {
+ this.unsub = BodyStore.listen(this._onBodyStoreEvent.bind(this));
+ }
+
+ componentWillUnmount() {
+ this.unsub();
+ }
+
+ _onBodyStoreEvent(evt) {
+ this.setState(this._getStateObject())
+ }
+
+ _getStateObject() {
+ return {
+ bmiFormatted: BodyStore.GetBMIFormatted(),
+ };
+ }
+
+ render() {
+ return (
+
+ }/>
+ );
+ }
+
+ renderScene(route, navigator) {
+ return (
+
+
+
+ {this.state.bmiFormatted}
+
+
+
+
+
+
+
+ );
+ }
+}
+
+var NavigationBarRouteMapper = {
+ LeftButton(route, navigator, index, nextState) {
+ return (
+ {navigator.parentNavigator.pop()}}>
+
+ Back
+
+
+ );
+ },
+ RightButton(route, navigator, index, nextState) {
+ return null;
+ },
+ Title(route, navigator, index, nextState) {
+ return (
+
+
+ Body Mass Index
+
+
+ );
+ }
+};
+
+
+module.exports = BodyMassIndex;
+export default BodyMassIndex;
diff --git a/examples/BodyMeasurements/app/components/dashboard/dashboard.js b/examples/BodyMeasurements/app/components/dashboard/dashboard.js
new file mode 100644
index 0000000000000000000000000000000000000000..6065754acc5110800824f430c79e86e6aae75bd7
--- /dev/null
+++ b/examples/BodyMeasurements/app/components/dashboard/dashboard.js
@@ -0,0 +1,127 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+import React, { Component } from 'react';
+import {
+ Navigator,
+ TouchableOpacity,
+ ScrollView,
+ Text,
+ View
+} from 'react-native';
+import TimerMixin from 'react-timer-mixin';
+var reactMixin = require('react-mixin');
+
+import styles from '../../styles/styles';
+import BodyStore from '../../stores/body';
+import DashboardItem from './item';
+
+
+class Dashboard extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = this._getStateObject();
+ }
+
+ componentDidMount() {
+ this.unsub = BodyStore.listen(this._onBodyStoreEvent.bind(this));
+ }
+
+ componentWillUnmount() {
+ this.unsub();
+ }
+
+ _onBodyStoreEvent(evt) {
+ this.setState(this._getStateObject())
+ }
+
+ _getStateObject() {
+ return {
+ weightFormatted: BodyStore.GetWeightFormatted(),
+ heightFormatted: BodyStore.GetHeightFormatted(),
+ bmiFormatted: BodyStore.GetBMIFormatted(),
+ bodyFatFormatted: BodyStore.GetBodyFatPercentageFormatted(),
+ leanBodyMassFormatted: BodyStore.GetLeanBodyMassFormatted(),
+ };
+ }
+
+ _onPressItem(key) {
+ console.log('_onPressItem() ==> ', key);
+ let self = this;
+ this.requestAnimationFrame(() => {
+ this.props.navigator.push({
+ name: key
+ });
+ })
+ }
+
+
+ render() {
+ return (
+
+ }/>
+ );
+ }
+
+ renderScene(route, navigator) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+reactMixin(Dashboard.prototype, TimerMixin);
+
+var NavigationBarRouteMapper = {
+ LeftButton(route, navigator, index, nextState) {
+ return null;
+ },
+ RightButton(route, navigator, index, nextState) {
+ return null;
+ },
+ Title(route, navigator, index, nextState) {
+ return (
+
+
+ HealthKit Body Measurements
+
+
+ );
+ }
+};
+
+
+module.exports = Dashboard;
+export default Dashboard;
diff --git a/examples/BodyMeasurements/app/components/dashboard/item.js b/examples/BodyMeasurements/app/components/dashboard/item.js
new file mode 100644
index 0000000000000000000000000000000000000000..694d838d584e225c063aa0e0fa222f88eafd5753
--- /dev/null
+++ b/examples/BodyMeasurements/app/components/dashboard/item.js
@@ -0,0 +1,87 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+import React, { Component } from 'react';
+import {
+ AppRegistry,
+ StyleSheet,
+ Navigator,
+ TouchableOpacity,
+ TouchableHighlight,
+ ScrollView,
+ Image,
+ Text,
+ View
+} from 'react-native';
+import styles from '../../styles/styles';
+
+const ICONS = {
+ "scale": require("../../assets/images/scale.png"),
+ "ruler": require("../../assets/images/ruler.png"),
+ "bmi": require("../../assets/images/bmi.png"),
+ "bodyfat": require("../../assets/images/bodyfat.png"),
+ "musclemass": require("../../assets/images/muscle-mass.png"),
+ "arrowright": require('../../assets/images/arrow-right.png'),
+ "heartbeat": require('../../assets/images/heartbeat.png')
+};
+
+
+class DashboardItem extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = this._getStateObject(this.props);
+ }
+
+ componentWillReceiveProps(newProps) {
+ this.setState(this._getStateObject(newProps));
+ }
+
+ _getStateObject(props) {
+ let label = props.label ? props.label : 'Label';
+ let value = props.value ? props.value : 'Value';
+ let iconSource = (props.icon && ICONS.hasOwnProperty(props.icon)) ? ICONS[props.icon] : ICONS.heartbeat;
+ return {label,value,iconSource};
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+ {this.state.label}
+
+
+
+ {this.state.value}
+
+
+
+
+
+
+ )
+ }
+}
+
+DashboardItem.propTypes = {
+ icon: React.PropTypes.string,
+ label: React.PropTypes.string,
+ value: React.PropTypes.string,
+ onPress: React.PropTypes.func
+};
+
+DashboardItem.defaultProps = {
+ onPress: function(){
+ console.log('default onPress()');
+ }
+};
+
+module.exports = DashboardItem;
+export default DashboardItem;
diff --git a/examples/BodyMeasurements/app/components/height/height.js b/examples/BodyMeasurements/app/components/height/height.js
new file mode 100644
index 0000000000000000000000000000000000000000..1d416fec6479a16ea9266acf722ed55fb97a4677
--- /dev/null
+++ b/examples/BodyMeasurements/app/components/height/height.js
@@ -0,0 +1,97 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+import React, { Component } from 'react';
+import {
+ Navigator,
+ TouchableOpacity,
+ Text,
+ View
+} from 'react-native';
+
+import styles from '../../styles/styles';
+import BodyStore from '../../stores/body';
+
+
+class Height extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = this._getStateObject();
+ }
+
+ componentDidMount() {
+ this.unsub = BodyStore.listen(this._onBodyStoreEvent.bind(this));
+ }
+
+ componentWillUnmount() {
+ this.unsub();
+ }
+
+ _onBodyStoreEvent(evt) {
+ this.setState(this._getStateObject())
+ }
+
+ _getStateObject() {
+ return {
+ heightFormatted: BodyStore.GetHeightFormatted(),
+ };
+ }
+
+ render() {
+ return (
+
+ }/>
+ );
+ }
+
+ renderScene(route, navigator) {
+ return (
+
+
+
+ {this.state.heightFormatted}
+
+
+
+
+
+
+
+ );
+ }
+}
+
+var NavigationBarRouteMapper = {
+ LeftButton(route, navigator, index, nextState) {
+ return (
+ {navigator.parentNavigator.pop()}}>
+
+ Back
+
+
+ );
+ },
+ RightButton(route, navigator, index, nextState) {
+ return null;
+ },
+ Title(route, navigator, index, nextState) {
+ return (
+
+
+ Height
+
+
+ );
+ }
+};
+
+
+module.exports = Height;
+export default Height;
diff --git a/examples/BodyMeasurements/app/components/leanBodyMass/leanBodyMass.js b/examples/BodyMeasurements/app/components/leanBodyMass/leanBodyMass.js
new file mode 100644
index 0000000000000000000000000000000000000000..f1a7ff1e57e79297e8d3e819de7a275791573f79
--- /dev/null
+++ b/examples/BodyMeasurements/app/components/leanBodyMass/leanBodyMass.js
@@ -0,0 +1,98 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+
+import React, { Component } from 'react';
+import {
+ Navigator,
+ TouchableOpacity,
+ Text,
+ View
+} from 'react-native';
+
+import styles from '../../styles/styles';
+import BodyStore from '../../stores/body';
+
+
+class LeanBodyMass extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = this._getStateObject();
+ }
+
+ componentDidMount() {
+ this.unsub = BodyStore.listen(this._onBodyStoreEvent.bind(this));
+ }
+
+ componentWillUnmount() {
+ this.unsub();
+ }
+
+ _onBodyStoreEvent(evt) {
+ this.setState(this._getStateObject())
+ }
+
+ _getStateObject() {
+ return {
+ leanBodyMassFormatted: BodyStore.GetLeanBodyMassFormatted(),
+ };
+ }
+
+ render() {
+ return (
+
+ }/>
+ );
+ }
+
+ renderScene(route, navigator) {
+ return (
+
+
+
+ {this.state.leanBodyMassFormatted}
+
+
+
+
+
+
+
+ );
+ }
+}
+
+var NavigationBarRouteMapper = {
+ LeftButton(route, navigator, index, nextState) {
+ return (
+ {navigator.parentNavigator.pop()}}>
+
+ Back
+
+
+ );
+ },
+ RightButton(route, navigator, index, nextState) {
+ return null;
+ },
+ Title(route, navigator, index, nextState) {
+ return (
+
+
+ Lean Body Mass
+
+
+ );
+ }
+};
+
+
+module.exports = LeanBodyMass;
+export default LeanBodyMass;
diff --git a/examples/BodyMeasurements/app/components/weight/weight.js b/examples/BodyMeasurements/app/components/weight/weight.js
new file mode 100644
index 0000000000000000000000000000000000000000..b5b6eb8840afea8b14b69b3628d7657cf07e658e
--- /dev/null
+++ b/examples/BodyMeasurements/app/components/weight/weight.js
@@ -0,0 +1,97 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+import React, { Component } from 'react';
+import {
+ Navigator,
+ TouchableOpacity,
+ Text,
+ View
+} from 'react-native';
+
+import styles from '../../styles/styles';
+import BodyStore from '../../stores/body';
+
+
+class Weight extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = this._getStateObject();
+ }
+
+ componentDidMount() {
+ this.unsub = BodyStore.listen(this._onBodyStoreEvent.bind(this));
+ }
+
+ componentWillUnmount() {
+ this.unsub();
+ }
+
+ _onBodyStoreEvent(evt) {
+ this.setState(this._getStateObject())
+ }
+
+ _getStateObject() {
+ return {
+ weightFormatted: BodyStore.GetWeightFormatted(),
+ };
+ }
+
+ render() {
+ return (
+
+ }/>
+ );
+ }
+
+ renderScene(route, navigator) {
+ return (
+
+
+
+ {this.state.weightFormatted}
+
+
+
+
+
+
+
+ );
+ }
+}
+
+var NavigationBarRouteMapper = {
+ LeftButton(route, navigator, index, nextState) {
+ return (
+ {navigator.parentNavigator.pop()}}>
+
+ Back
+
+
+ );
+ },
+ RightButton(route, navigator, index, nextState) {
+ return null;
+ },
+ Title(route, navigator, index, nextState) {
+ return (
+
+
+ Weight
+
+
+ );
+ }
+};
+
+
+module.exports = Weight;
+export default Weight;
diff --git a/examples/BodyMeasurements/app/stores/body.js b/examples/BodyMeasurements/app/stores/body.js
new file mode 100644
index 0000000000000000000000000000000000000000..fac640213b42a439f9d598a909a7e4f9b511a05e
--- /dev/null
+++ b/examples/BodyMeasurements/app/stores/body.js
@@ -0,0 +1,308 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+
+var airflux = require( 'airflux' );
+var _ = require('lodash');
+var moment = require('moment');
+var Immutable = require('immutable');
+//var actions = require('../actions/actions');
+
+var AppleHealthKit = require('react-native-apple-healthkit');
+
+var DATA = {
+ weight: 0,
+ height: 0,
+ bmi: 0,
+ bodyFatPercentage: 0,
+ leanBodyMass: 0,
+ steps: 0,
+};
+
+/**
+ * @namespace Stores
+ */
+
+/**
+ * @class WeightStore
+ * @classdesc Airflux store to handle data, actions, and events relating to the WeightStore
+ * @memberof Stores
+ */
+class BodyStore extends airflux.Store {
+
+ /**
+ * Initialize the WeightStore, optionally with 'props' object
+ * @constructs Stores.TestingEventService
+ * @param {object} props - an optional properties object to initialize the store with
+ *
+ */
+ constructor(props) {
+ //console.log("WeightStore props --> ", props);
+ super(props);
+ let self = this;
+
+ //this.listenTo(actions.addWeight, this._onactn_addWeight)
+
+ this._initHealthKit = this._initHealthKit.bind(this);
+ this._fetchHealthKitUserWeight = this._fetchHealthKitUserWeight.bind(this);
+ this._fetchHealthKitUserHeight = this._fetchHealthKitUserHeight.bind(this);
+ this._fetchHealthKitUserBmi = this._fetchHealthKitUserBmi.bind(this);
+ this._fetchHealthKitStepCountToday = this._fetchHealthKitStepCountToday.bind(this);
+ this._fetchHealthKitBodyFatPercentage = this._fetchHealthKitBodyFatPercentage.bind(this);
+ this._fetchHealthKitLeanBodyMass = this._fetchHealthKitLeanBodyMass.bind(this);
+ this.GetWeightValue = this.GetWeightValue.bind(this);
+ this.GetWeightFormatted = this.GetWeightFormatted.bind(this);
+ this.GetSteps = this.GetSteps.bind(this);
+ this.GetHeightFormatted = this.GetHeightFormatted.bind(this);
+ this.GetHeightValue = this.GetHeightValue.bind(this);
+ this.GetBMIValue = this.GetBMIValue.bind(this);
+ this.GetBMIFormatted = this.GetBMIFormatted.bind(this);
+ this.GetBodyFatPercentageValue = this.GetBodyFatPercentageValue.bind(this);
+ this.GetBodyFatPercentageFormatted = this.GetBodyFatPercentageFormatted.bind(this);
+ this.GetLeanBodyMassValue = this.GetLeanBodyMassValue.bind(this);
+ this.GetLeanBodyMassFormatted = this.GetLeanBodyMassFormatted.bind(this);
+
+ AppleHealthKit.isAvailable((err,available) => {
+ console.log('AppleHealthKit.isAvailable(): ', available);
+ if(available){
+ self._initHealthKit();
+ }
+ });
+
+ //AppleHealthKit.getInfo({init:"true"}, (err,res) => {
+ // if(err) {
+ // console.log("ERROR GETTING HEALTHKIT MODULE INFO");
+ // console.log(err);
+ // return;
+ // }
+ // console.log("HEALTHKIT MODULE INFO: ", res);
+ //});
+ }
+
+
+ _initHealthKit() {
+ let self = this;
+
+ let healthKitOptions = {
+ permissions: {
+ read: ["Height", "Weight", "Steps", "DateOfBirth", "BodyMassIndex", "LeanBodyMass", "BodyFatPercentage"],
+ write: ["Weight"]
+ }
+ };
+
+ AppleHealthKit.initHealthKit(healthKitOptions, (err, res) => {
+ if(this._handleHealthKitError(err, 'initHealthKit')){
+ return;
+ }
+ console.log("HEALTHKIT INITIALIZED!! ", res);
+
+ self._fetchHealthKitUserWeight();
+ self._fetchHealthKitUserBmi();
+ self._fetchHealthKitStepCountToday();
+ self._fetchHealthKitUserHeight();
+ self._fetchHealthKitBodyFatPercentage();
+ self._fetchHealthKitLeanBodyMass();
+ });
+ }
+
+
+ _handleHealthKitError(err, method) : boolean {
+ if(err){
+ let errStr = 'HealthKit_ERROR['+method+'] : ';
+ if(typeof err === 'string'){
+ errStr += err;
+ } else if (typeof err === 'object' && err.message){
+ errStr += err.message;
+ }
+ console.log(errStr);
+ return true;
+ }
+ return false;
+ }
+
+ _onactn_addWeight(options) {
+ console.log('_onactn_addWeight() --> ', options);
+ if(options && options.weight){
+ let weightVal = parseFloat(options.weight);
+ let self = this;
+ AppleHealthKit.saveWeight({weight:weightVal}, (err, res) => {
+ if(this._handleHealthKitError(err, 'saveWeight')){
+ return;
+ }
+ DATA.weight = weightVal;
+ self.trigger({
+ name: 'change:weight',
+ target: null,
+ data: DATA.weight
+ });
+ });
+ }
+ }
+
+
+ _fetchHealthKitUserWeight() {
+ let self = this;
+ AppleHealthKit.getCurrentWeight(null, (err, weight) => {
+ if(this._handleHealthKitError(err, 'getCurrentWeight')){
+ return;
+ }
+ weight = _.round(weight,1);
+
+ DATA.weight = weight;
+ self.trigger({
+ name: 'change:weight',
+ target: null,
+ data: weight
+ });
+ });
+ }
+
+
+ _fetchHealthKitUserHeight() {
+ let self = this;
+ AppleHealthKit.getMostRecentHeight(null, (err, height) => {
+ if(this._handleHealthKitError(err, 'getMostRecentHeight')){
+ return;
+ }
+ console.log("HEIGHT: ", height);
+
+ if(typeof height === "number" && height > 0){
+ DATA.height = height;
+ self.trigger({
+ name: 'change:height',
+ target: null,
+ data: height
+ });
+ }
+ });
+ }
+
+
+ _fetchHealthKitUserBmi() {
+ let self = this;
+ AppleHealthKit.getLatestBmi({blah:true}, (err, bmi) => {
+ if(this._handleHealthKitError(err, 'getLatestBmi')){
+ return;
+ }
+ console.log("LATEST BMI: ", bmi);
+ if(bmi && bmi.value){
+ DATA.bmi = _.round(bmi.value,1);
+ self.trigger({
+ name: 'change:bmi',
+ target: null,
+ data: DATA.bmi
+ });
+ }
+ });
+ }
+
+
+ _fetchHealthKitBodyFatPercentage() {
+ let self = this;
+ AppleHealthKit.getMostRecentBodyFatPercentage({blah:true}, (err, fatPercentage) => {
+ if(this._handleHealthKitError(err, 'getMostRecentBodyFatPercentage')){
+ return;
+ }
+ console.log("BODY FAT PERCENTAGE: ", fatPercentage);
+ DATA.bodyFatPercentage = fatPercentage;
+ self.trigger({
+ name: 'change:body_fat_percentage',
+ target: null,
+ data: DATA.bodyFatPercentage
+ });
+ });
+ }
+
+
+ _fetchHealthKitLeanBodyMass() {
+ let self = this;
+ AppleHealthKit.getMostRecentLeanBodyMass({blah:true}, (err, leanMass) => {
+ if(this._handleHealthKitError(err, 'getMostRecentLeanBodyMass')){
+ return;
+ }
+ console.log("LEAN BODY MASS: ", leanMass);
+ DATA.leanBodyMass = _.round(leanMass,0);
+ self.trigger({
+ name: 'change:lean_body_mass',
+ target: null,
+ data: DATA.leanBodyMass
+ });
+ });
+ }
+
+
+
+ _fetchHealthKitStepCountToday() {
+ let self = this;
+ AppleHealthKit.getStepCountForToday({options:"true"}, (err, steps) => {
+ if(this._handleHealthKitError(err, 'getStepCountForToday')){
+ return;
+ }
+ console.log("STEPS : ", steps);
+ steps = _.round(steps,0);
+
+ DATA.steps = steps;
+ self.trigger({
+ name: 'change:steps',
+ target: null,
+ data: steps
+ });
+ });
+ }
+
+
+ GetHeightValue() {
+ return DATA.height;
+ }
+
+ GetHeightFormatted() {
+ let feet = _.floor((DATA.height / 12));
+ let inches = DATA.height % 12;
+ let formatted = '' + feet + '\'' + inches + '"';
+ return formatted;
+ }
+
+ GetWeightValue() {
+ return DATA.weight;
+ }
+
+ GetWeightFormatted() {
+ return DATA.weight + ' lbs';
+ }
+
+ GetBMIValue() {
+ return DATA.bmi;
+ }
+
+ GetBMIFormatted() {
+ return '' + DATA.bmi;
+ }
+
+ GetBodyFatPercentageValue() {
+ return DATA.bodyFatPercentage;
+ }
+
+ GetBodyFatPercentageFormatted() {
+ return '' + DATA.bodyFatPercentage + '%';
+ }
+
+ GetLeanBodyMassValue() {
+ return DATA.leanBodyMass;
+ }
+
+ GetLeanBodyMassFormatted() {
+ return '' + DATA.leanBodyMass + ' lbs';
+ }
+
+
+ GetSteps() {
+ return DATA.steps;
+ }
+
+}
+
+
+let storeInstance = new BodyStore();
+export default storeInstance;
+module.exports = storeInstance;
\ No newline at end of file
diff --git a/examples/BodyMeasurements/app/styles/styles.js b/examples/BodyMeasurements/app/styles/styles.js
new file mode 100644
index 0000000000000000000000000000000000000000..d96fb7f9952638914e85ecfd4035176639121fd6
--- /dev/null
+++ b/examples/BodyMeasurements/app/styles/styles.js
@@ -0,0 +1,186 @@
+/**
+ * Created by greg on 2016-06-27.
+ */
+
+import {
+ Platform,
+ StyleSheet
+} from 'react-native';
+
+
+
+const styles = StyleSheet.create({
+
+ sceneContainerNavbar: {
+ flex: 1,
+ flexDirection: 'column',
+ //justifyContent: 'flex-start',
+ //alignItems: 'flex-start',
+ marginTop: (Platform.OS === 'ios') ? 64 : 54,
+ backgroundColor: '#FFFFFF'
+ },
+
+ navigationBar: {
+ borderBottomWidth: 1,
+ borderBottomColor: '#cccccc',
+ backgroundColor: '#f5f5f5'
+ },
+
+ navbarTitleTouchable: {
+ flex: 1,
+ justifyContent: 'center'
+ },
+ navbarTitle: {
+ color: '#FD2D55',
+ margin: 10,
+ fontSize: 18
+ },
+
+
+ row_1_3: {
+ flex: 0.33,
+ flexDirection:'column',
+ padding:10,
+ //backgroundColor: '#FF8000'
+ },
+
+ row_2_3: {
+ flex: 0.66,
+ flexDirection:'column',
+ padding:10,
+ //backgroundColor: '#0088cc'
+ },
+
+ borderTopLightGrey: {
+ borderTopColor: '#CCCCCC',
+ borderTopWidth: 1,
+ },
+
+ largeCenteredText: {
+ textAlign: 'center',
+ flexDirection:'row',
+ fontSize:34,
+ marginTop:60,
+ },
+
+ dashboardListItemLabel: {
+ fontSize:12,
+ color: '#FD2D55',
+ position:'absolute',
+ left: 70,
+ top:0,
+ },
+
+ dashboardListItemValue: {
+ fontSize:22,
+ color: '#47a292',
+ position:'absolute',
+ left: 70,
+ top:15,
+ },
+
+ sceneContainerFull: {
+ flex: 1,
+ flexDirection: 'column',
+ //justifyContent: 'flex-start',
+ //alignItems: 'flex-start',
+ marginTop: 0,
+ backgroundColor: '#FFFFFF'
+ },
+
+
+ dashboardToday: {
+ height: 30,
+ alignItems: 'stretch',
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: 'rgba(162, 162, 162, 0.2)',
+ },
+ dashboardTodayText: {
+
+ color: '#a2a2a2',
+ },
+
+ dashboardListItemHighlight: {
+ flexDirection: 'row',
+ alignSelf: 'stretch',
+ justifyContent: 'center',
+ //flex:1,
+ //alignSelf: 'stretch',
+ //overflow: 'hidden',
+ },
+
+ dashboardListItemView: {
+ flex: 1,
+ //backgroundColor: '#FDFDFD',
+ backgroundColor: '#FDFDFD',
+ //paddingTop:74,
+ //flexDirection: 'row',
+ flexDirection: 'column',
+ alignSelf: 'stretch',
+ justifyContent: 'flex-start',
+ alignItems: 'flex-start',
+ paddingTop:15,
+ paddingBottom: 15,
+
+ //flexWrap: 'wrap',
+
+ borderBottomColor: '#AAAAAA',
+ borderBottomWidth: 1,
+ },
+
+ dashboardListItemViewTransparent: {
+ flex: 1,
+ //backgroundColor: '#FDFDFD',
+ backgroundColor: 'transparent',
+ //paddingTop:74,
+ //flexDirection: 'row',
+ flexDirection: 'column',
+ alignSelf: 'stretch',
+ justifyContent: 'flex-start',
+ alignItems: 'flex-start',
+ paddingTop:15,
+ paddingBottom: 15,
+
+ //flexWrap: 'wrap',
+
+ borderBottomColor: '#AAAAAA',
+ borderBottomWidth: 1,
+ },
+
+ dashboardListItem: {
+ flexDirection: 'row',
+ alignSelf: 'stretch',
+ justifyContent: 'space-between',
+ flex:1,
+ backgroundColor: 'transparent',
+ },
+
+
+ dashboardListItemIcon: {
+ width: 40,
+ height: 40,
+ marginLeft: 10,
+ opacity:0.7,
+ //marginTop: 50,
+ //backgroundColor: 'transparent',
+ alignSelf: 'flex-start',
+ },
+
+ dashboardListItemText: {
+ flex: 1,
+ flexDirection: 'column',
+ alignSelf: 'flex-start',
+ marginLeft: 20,
+ fontSize: 29,
+ color: '#47a292',
+ //color: '#98CA3F',
+ //color: '#644496',
+ flexWrap: 'wrap',
+ backgroundColor:'transparent',
+ },
+
+});
+
+module.exports = styles;
+export default styles;
diff --git a/examples/BodyMeasurements/index.ios.js b/examples/BodyMeasurements/index.ios.js
index 3ca7816cdd1acd3b98c2b3b6c3b34ce555bdbc19..4c771b724615ac0c2080c44c003e0348e433d7ad 100644
--- a/examples/BodyMeasurements/index.ios.js
+++ b/examples/BodyMeasurements/index.ios.js
@@ -13,67 +13,14 @@ import {
View
} from 'react-native';
-
-let Index = require('./src/components/Index');
-
+let App = require('./app/app');
class BodyMeasurements extends Component {
render() {
return (
-
- );
-
- //
- //
- //return (
- //
- //
- // Welcome to React Native!
- //
- //
- // To get started, edit index.ios.js
- //
- //
- // Press Cmd+R to reload,{'\n'}
- // Cmd+D or shake for dev menu
- //
- //
- //);
+
+ )
}
-
-
- renderScene(route, navigator) {
- if(route.name == 'Index') {
- return
- }
- //if(route.name == 'Home') {
- // return
- //}
- }
-
-
}
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: '#F5FCFF',
- },
- welcome: {
- fontSize: 20,
- textAlign: 'center',
- margin: 10,
- },
- instructions: {
- textAlign: 'center',
- color: '#333333',
- marginBottom: 5,
- },
-});
-
AppRegistry.registerComponent('BodyMeasurements', () => BodyMeasurements);
diff --git a/examples/BodyMeasurements/ios/BodyMeasurements.xcodeproj/project.pbxproj b/examples/BodyMeasurements/ios/BodyMeasurements.xcodeproj/project.pbxproj
index 5ad2d79565ef5c4255e88429248b3f2c86ab0630..49b92db3b8d5122c3ec7ed0331a7055170698992 100644
--- a/examples/BodyMeasurements/ios/BodyMeasurements.xcodeproj/project.pbxproj
+++ b/examples/BodyMeasurements/ios/BodyMeasurements.xcodeproj/project.pbxproj
@@ -22,6 +22,8 @@
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
+ 37E9B8741D21B52F0090B19B /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37E9B8731D21B52F0090B19B /* HealthKit.framework */; };
+ 37E9B89D1D21C63C0090B19B /* libRCTAppleHealthKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 37E9B89C1D21C6380090B19B /* libRCTAppleHealthKit.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
/* End PBXBuildFile section */
@@ -89,6 +91,13 @@
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
remoteInfo = React;
};
+ 37E9B89B1D21C6380090B19B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 37E9B8971D21C6380090B19B /* RCTAppleHealthKit.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 3774C88D1D2092F20000B3F3;
+ remoteInfo = RCTAppleHealthKit;
+ };
78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
@@ -125,6 +134,9 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = BodyMeasurements/Info.plist; sourceTree = ""; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = BodyMeasurements/main.m; sourceTree = ""; };
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; };
+ 37E9B8731D21B52F0090B19B /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
+ 37E9B8751D21B52F0090B19B /* BodyMeasurements.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = BodyMeasurements.entitlements; path = BodyMeasurements/BodyMeasurements.entitlements; sourceTree = ""; };
+ 37E9B8971D21C6380090B19B /* RCTAppleHealthKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAppleHealthKit.xcodeproj; path = "../node_modules/react-native-apple-healthkit/RCTAppleHealthKit.xcodeproj"; sourceTree = ""; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; };
/* End PBXFileReference section */
@@ -142,8 +154,10 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 37E9B89D1D21C63C0090B19B /* libRCTAppleHealthKit.a in Frameworks */,
146834051AC3E58100842450 /* libReact.a in Frameworks */,
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
+ 37E9B8741D21B52F0090B19B /* HealthKit.framework in Frameworks */,
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
@@ -234,6 +248,7 @@
13B07FAE1A68108700A75B9A /* BodyMeasurements */ = {
isa = PBXGroup;
children = (
+ 37E9B8751D21B52F0090B19B /* BodyMeasurements.entitlements */,
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
@@ -253,6 +268,14 @@
name = Products;
sourceTree = "";
};
+ 37E9B8981D21C6380090B19B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 37E9B89C1D21C6380090B19B /* libRCTAppleHealthKit.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
78C398B11ACF4ADC00677621 /* Products */ = {
isa = PBXGroup;
children = (
@@ -264,6 +287,7 @@
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
+ 37E9B8971D21C6380090B19B /* RCTAppleHealthKit.xcodeproj */,
146833FF1AC3E56700842450 /* React.xcodeproj */,
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
@@ -289,6 +313,7 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
+ 37E9B8731D21B52F0090B19B /* HealthKit.framework */,
13B07FAE1A68108700A75B9A /* BodyMeasurements */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* BodyMeasurementsTests */,
@@ -359,6 +384,14 @@
CreatedOnToolsVersion = 6.2;
TestTargetID = 13B07F861A680F5B00A75B9A;
};
+ 13B07F861A680F5B00A75B9A = {
+ DevelopmentTeam = 95ZTJFHCUG;
+ SystemCapabilities = {
+ com.apple.HealthKit = {
+ enabled = 1;
+ };
+ };
+ };
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "BodyMeasurements" */;
@@ -377,6 +410,10 @@
ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
},
+ {
+ ProductGroup = 37E9B8981D21C6380090B19B /* Products */;
+ ProjectRef = 37E9B8971D21C6380090B19B /* RCTAppleHealthKit.xcodeproj */;
+ },
{
ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
@@ -479,6 +516,13 @@
remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
+ 37E9B89C1D21C6380090B19B /* libRCTAppleHealthKit.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRCTAppleHealthKit.a;
+ remoteRef = 37E9B89B1D21C6380090B19B /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -605,6 +649,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_ENTITLEMENTS = BodyMeasurements/BodyMeasurements.entitlements;
DEAD_CODE_STRIPPING = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
@@ -625,6 +670,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_ENTITLEMENTS = BodyMeasurements/BodyMeasurements.entitlements;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
diff --git a/examples/BodyMeasurements/ios/BodyMeasurements/BodyMeasurements.entitlements b/examples/BodyMeasurements/ios/BodyMeasurements/BodyMeasurements.entitlements
new file mode 100644
index 0000000000000000000000000000000000000000..e10f4302d524a2c6313dc968df134285905acfc8
--- /dev/null
+++ b/examples/BodyMeasurements/ios/BodyMeasurements/BodyMeasurements.entitlements
@@ -0,0 +1,8 @@
+
+
+
+
+ com.apple.developer.healthkit
+
+
+
diff --git a/examples/BodyMeasurements/ios/BodyMeasurements/Info.plist b/examples/BodyMeasurements/ios/BodyMeasurements/Info.plist
index 970fc6ac629ed4808f668e843326eb54c8850638..1680bf7e82c75d70cc371b972e9ddfb804930c34 100644
--- a/examples/BodyMeasurements/ios/BodyMeasurements/Info.plist
+++ b/examples/BodyMeasurements/ios/BodyMeasurements/Info.plist
@@ -23,11 +23,10 @@
LSRequiresIPhoneOS
NSAppTransportSecurity
-
-
- NSAllowsArbitraryLoads
-
-
+
+ NSAllowsArbitraryLoads
+
+
NSLocationWhenInUseUsageDescription
UILaunchStoryboardName
@@ -35,6 +34,7 @@
UIRequiredDeviceCapabilities
armv7
+ healthkit
UISupportedInterfaceOrientations
diff --git a/examples/BodyMeasurements/package.json b/examples/BodyMeasurements/package.json
index 66c304e7906a090fcdc37ff7b7576cb77160db64..42c0e9910ae06b5c0b8d1699078319a4032c5e3d 100644
--- a/examples/BodyMeasurements/package.json
+++ b/examples/BodyMeasurements/package.json
@@ -6,7 +6,10 @@
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
+ "airflux": "^0.5.1",
"react": "15.1.0",
- "react-native": "^0.28.0"
+ "react-mixin": "^2.0.2",
+ "react-native": "^0.28.0",
+ "react-native-apple-healthkit": "file:///Users/greg/Dev/experimental/RCTAppleHealthKit"
}
}