Skip to content

Commit

Permalink
Energy burnt
Browse files Browse the repository at this point in the history
* Add Calories Burnt as IOS Method

* Add getCalories in for Android

* Add getDistance in index

* Update Readme and add missing call to index.js

* Add Authorization for GetCalories

* Add Authorization for Android
  • Loading branch information
Francesco-Voto authored and scerelli committed Dec 6, 2019
1 parent df76060 commit 9c7f149
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ Fetch steps on a given period of time. It requires an `Object` with `startDate`
- **Fitness.getDistance(dates: { startDate: string, endDate: string })**
Fetch distance in meters on a given period of time. It requires an `Object` with `startDate` and `endDate` attributes as string. If startDate is not provided an error will be thrown.

- **Fitness.getCalories(dates: { startDate: string, endDate: string })**
Fetch calories burnt in kilocalories on a given period of time. It requires an `Object` with `startDate` and `endDate` attributes as string. If startDate is not provided an error will be thrown.

- **Fitness.subscribeToActivity()**
Available only on android. Subscribe to all Google Fit activities. It returns a promise with `true` for a successful subscription and `false` otherwise.
Call this function to get all google fit activites and eliminate the need to have Google Fit installed on the device.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,13 @@ public void getDistance(double startDate, double endDate, Promise promise){
promise.reject(e);
}
}

@ReactMethod
public void getCalories(double startDate, double endDate, Promise promise){
try {
manager.getCalories(getCurrentActivity(), startDate, endDate, promise);
}catch(Error e){
promise.reject(e);
}
}
}
53 changes: 53 additions & 0 deletions android/src/main/java/com/ovalmoney/fitness/manager/Manager.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public boolean isAuthorized(final Activity activity){
.addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_ACTIVITY_SAMPLES, FitnessOptions.ACCESS_WRITE)
.addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE, FitnessOptions.ACCESS_WRITE)
.addDataType(DataType.TYPE_CALORIES_EXPENDED, FitnessOptions.ACCESS_WRITE)
.build();
return GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(activity), fitnessOptions);
}
Expand All @@ -76,6 +77,7 @@ public void requestPermissions(@NonNull Activity currentActivity, Promise promis
.addDataType(DataType.TYPE_DISTANCE_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_ACTIVITY_SAMPLES, FitnessOptions.ACCESS_WRITE)
.addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE, FitnessOptions.ACCESS_WRITE)
.addDataType(DataType.TYPE_CALORIES_EXPENDED, FitnessOptions.ACCESS_WRITE)
.build();
GoogleSignIn.requestPermissions(
currentActivity,
Expand Down Expand Up @@ -218,6 +220,43 @@ public void onComplete(@NonNull Task<DataReadResponse> task) {
});
}

public void getCalories(Context context, double startDate, double endDate, final Promise promise) {
DataReadRequest readRequest = new DataReadRequest.Builder()
.aggregate(DataType.TYPE_CALORIES_EXPENDED, DataType.AGGREGATE_CALORIES_EXPENDED)
.bucketByTime(1, TimeUnit.DAYS)
.setTimeRange((long) startDate, (long) endDate, TimeUnit.MILLISECONDS)
.build();

Fitness.getHistoryClient(context, GoogleSignIn.getLastSignedInAccount(context))
.readData(readRequest)
.addOnSuccessListener(new OnSuccessListener<DataReadResponse>() {
@Override
public void onSuccess(DataReadResponse dataReadResponse) {
if (dataReadResponse.getBuckets().size() > 0) {
WritableArray calories = Arguments.createArray();
for (Bucket bucket : dataReadResponse.getBuckets()) {
List<DataSet> dataSets = bucket.getDataSets();
for (DataSet dataSet : dataSets) {
processDistance(dataSet, distances);
}
}
promise.resolve(distances);
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
promise.reject(e);
}
})
.addOnCompleteListener(new OnCompleteListener<DataReadResponse>() {
@Override
public void onComplete(@NonNull Task<DataReadResponse> task) {
}
});
}

private void processStep(DataSet dataSet, WritableArray map) {

WritableMap stepMap = Arguments.createMap();
Expand Down Expand Up @@ -245,4 +284,18 @@ private void processDistance(DataSet dataSet, WritableArray map) {
}
}
}

private void processCalories(DataSet dataSet, WritableArray map) {

WritableMap caloryMap = Arguments.createMap();

for (DataPoint dp : dataSet.getDataPoints()) {
for(Field field : dp.getDataType().getFields()) {
caloryMap.putString("startDate", dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS)));
caloryMap.putString("endDate", dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS)));
caloryMap.putDouble("quantity", dp.getValue(field).asFloat());
map.pushMap(caloryMap);
}
}
}
}
63 changes: 63 additions & 0 deletions ios/RCTFitness/RCTFitness.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ - (NSDictionary *)constantsToExport{
NSMutableSet *perms = [NSMutableSet setWithCapacity:1];
[perms addObject:[HKObjectType quantityTypeForIdentifier: HKQuantityTypeIdentifierDistanceWalkingRunning]];
[perms addObject:[HKObjectType quantityTypeForIdentifier: HKQuantityTypeIdentifierStepCount]];
[perms addObject:[HKObjectType quantityTypeForIdentifier: HKQuantityTypeIdentifierActiveEnergyBurned]];
[self.healthStore requestAuthorizationToShareTypes:nil readTypes:perms completion:^(BOOL success, NSError *error) {
if (!success) {
NSError * error = [RCTFitness createErrorWithCode:ErrorHKNotAvailable andDescription:RCT_ERROR_HK_NOT_AVAILABLE];
Expand All @@ -75,6 +76,7 @@ - (NSDictionary *)constantsToExport{
NSMutableSet *perms = [NSMutableSet setWithCapacity:1];
[perms addObject:[HKObjectType quantityTypeForIdentifier: HKQuantityTypeIdentifierDistanceWalkingRunning]];
[perms addObject:[HKObjectType quantityTypeForIdentifier: HKQuantityTypeIdentifierStepCount]];
[perms addObject:[HKObjectType quantityTypeForIdentifier: HKQuantityTypeIdentifierActiveEnergyBurned]];

[self.healthStore getRequestStatusForAuthorizationToShareTypes:[NSSet set] readTypes:perms completion:^(HKAuthorizationRequestStatus status, NSError *error) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
Expand Down Expand Up @@ -222,6 +224,67 @@ - (NSDictionary *)constantsToExport{
[self.healthStore executeQuery:query];
}

RCT_REMAP_METHOD(getCalories,
withStartDate: (double) startDate
andEndDate: (double) endDate
withCaloriesResolver:(RCTPromiseResolveBlock)resolve
andCaloriesRejecter:(RCTPromiseRejectBlock)reject){

if(!startDate){
NSError * error = [RCTFitness createErrorWithCode:ErrorDateNotCorrect andDescription:RCT_ERROR_DATE_NOT_CORRECT];
[RCTFitness handleRejectBlock:reject error:error];
return;
}
HKQuantityType *type =
[HKObjectType quantityTypeForIdentifier: HKQuantityTypeIdentifierActiveEnergyBurned];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *interval = [[NSDateComponents alloc] init];
interval.day = 1;

NSDateComponents *anchorComponents = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear
fromDate:[NSDate date]];
anchorComponents.hour = 0;
NSDate *anchorDate = [calendar dateFromComponents:anchorComponents];
HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:type
quantitySamplePredicate:nil
options:HKStatisticsOptionCumulativeSum
anchorDate:anchorDate
intervalComponents:interval];
query.initialResultsHandler =
^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *results, NSError *error) {

if (error) {
NSError * error = [RCTFitness createErrorWithCode:ErrorNoEvents andDescription:RCT_ERROR_NO_EVENTS];
[RCTFitness handleRejectBlock:reject error:error];
return;
}

NSDate * sd = [RCTFitness dateFromTimeStamp: startDate / 1000];
NSDate * ed = [RCTFitness dateFromTimeStamp: endDate / 1000];

NSMutableArray *data = [NSMutableArray arrayWithCapacity:1];
[results
enumerateStatisticsFromDate: sd
toDate:ed
withBlock:^(HKStatistics *result, BOOL *stop) {
HKQuantity *quantity = result.sumQuantity;
if (quantity) {
NSDictionary *elem = @{
@"quantity" : @([quantity doubleValueForUnit:[HKUnit kilocalorieUnit]]),
@"startDate" : [RCTFitness ISO8601StringFromDate: result.startDate],
@"endDate" : [RCTFitness ISO8601StringFromDate: result.endDate],
};
[data addObject:elem];
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
resolve(data);
});
};

[self.healthStore executeQuery:query];
}

@end


10 changes: 10 additions & 0 deletions js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ const getSteps = ({ startDate, endDate }) =>
const getDistance = ({ startDate, endDate }) =>
NativeModules.Fitness.getDistance(parseDate(startDate), parseDate(endDate));

/**
* Get native getCalories with parsed Dates
* @param startDate
* @param endDate
* @returns {*}
*/
const getCalories = ({ startDate, endDate }) =>
NativeModules.Fitness.getCalories(parseDate(startDate), parseDate(endDate));

/**
* Check if valid date and parse it
* @param date: Date to parse
Expand All @@ -38,4 +47,5 @@ export default {
...NativeModules.Fitness,
getSteps,
getDistance,
getCalories,
};

0 comments on commit 9c7f149

Please sign in to comment.