public void SaveWorkout(HKWorkoutSession workoutSession, NSDate startDate, NSDate endDate) { // Create and save a workout sample var configuration = workoutSession.WorkoutConfiguration; var metadata = new HKMetadata { IndoorWorkout = configuration.LocationType == HKWorkoutSessionLocationType.Indoor, }; var workout = HKWorkout.Create(configuration.ActivityType, startDate, endDate, this.workoutEvents.ToArray(), this.TotalBurningEnergyQuantity(), this.TotalDistanceQuantity(), metadata); this.healthStore.SaveObject(workout, (isSuccess, error) => { if (isSuccess) { this.AddSamples(workout, startDate, endDate); } }); }
public override void Awake(NSObject context) { base.Awake(context); this.workout = context as HKWorkout; this.SetTitle("Summary"); }
private void MakeWorkoutsSlothy(HKWorkout workout) { // Query for workout's rotes var routeType = HKSeriesType.WorkoutRouteType; var workoutPredicate = HKQuery.GetPredicateForObjectsFromWorkout(workout); var routeQuery = new HKSampleQuery(routeType, workoutPredicate, HKSampleQuery.NoLimit, null, (sender, results, error) => { var route = results?.FirstOrDefault() as HKWorkoutRoute; if (route != null) { var version = route.Metadata?.SyncVersion; if (!version.HasValue) { Console.WriteLine($"Route does not have a sync version ({route})"); } else if (version.Value == 1) { this.MakeRouteWorkoutsSlothy(workout, route); } } else { Console.WriteLine($"An error occurred fetching the route ({error?.LocalizedDescription ?? "Workout has no routes"})"); } }); this.healthStore.ExecuteQuery(routeQuery); }
private void MakeRouteWorkoutsSlothy(HKWorkout workout, HKWorkoutRoute route) { // Get all of the locations this.LoadRouteLocations(route, (locations) => { // Slothify route var newLocations = this.SlothifyRouteLocations(locations); this.UpdateWorkoutLocationsRoute(workout, route, newLocations); }); }
public void SaveWorkout() { // Obtain the `HKObjectType` for active energy burned. var activeEnergyType = HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned); if (activeEnergyType == null) { return; } var beginDate = WorkoutBeginDate; var endDate = WorkoutEndDate; var timeDifference = endDate.Subtract(beginDate); double duration = timeDifference.TotalSeconds; NSDictionary metadata = null; var workout = HKWorkout.Create(HKWorkoutActivityType.Walking, (NSDate)beginDate, (NSDate)endDate, duration, CurrentActiveEnergyQuantity, HKQuantity.FromQuantity(HKUnit.Mile, 0.0), metadata); var finalActiveEnergySamples = ActiveEnergySamples; if (HealthStore.GetAuthorizationStatus(activeEnergyType) != HKAuthorizationStatus.SharingAuthorized || HealthStore.GetAuthorizationStatus(HKObjectType.GetWorkoutType()) != HKAuthorizationStatus.SharingAuthorized) { return; } HealthStore.SaveObject(workout, (success, error) => { if (!success) { Console.WriteLine($"An error occured saving the workout. In your app, try to handle this gracefully. The error was: {error}."); return; } if (finalActiveEnergySamples.Count > 0) { HealthStore.AddSamples(finalActiveEnergySamples.ToArray(), workout, (addSuccess, addError) => { // Handle any errors if (addError != null) { Console.WriteLine($"An error occurred adding the samples. In your app, try to handle this gracefully. The error was: {error.ToString()}."); } }); } }); }
//More info for init HKUnit: //https://developer.apple.com/documentation/healthkit/hkunit/1615733-init //More info on datatype: //https://github.com/dariosalvi78/cordova-plugin-health //TODO: come gestire active+basal per calorie? //TODO: HKQuantityTypeIdentifierActiveEnergyBurned + HKQuantityTypeIdentifierBasalEnergyBurned internal static WorkoutDataType WorkoutDataType(this HKWorkout hKWorkout) { return(hKWorkout.WorkoutActivityType switch { HKWorkoutActivityType.Flexibility => Health.WorkoutDataType.Flexibility, HKWorkoutActivityType.Cycling => Health.WorkoutDataType.Biking, HKWorkoutActivityType.MindAndBody => Health.WorkoutDataType.MindAndBody, HKWorkoutActivityType.FunctionalStrengthTraining => Health.WorkoutDataType.FunctionalStrengthTraining, HKWorkoutActivityType.TraditionalStrengthTraining => Health.WorkoutDataType.TraditionalStrengthTraining, HKWorkoutActivityType.Yoga => Health.WorkoutDataType.Yoga, HKWorkoutActivityType.Running => Health.WorkoutDataType.Running, HKWorkoutActivityType.CoreTraining => Health.WorkoutDataType.CoreTraining, HKWorkoutActivityType.Other => Health.WorkoutDataType.Other, _ => throw new NotSupportedException(), });
private void AddSamples(HKWorkout workout, NSDate startDate, NSDate endDate) { // Create energy and distance sample var totalEnergyBurnedSample = HKQuantitySample.FromType(HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned), this.TotalBurningEnergyQuantity(), startDate, endDate); var totalDistanceSample = HKQuantitySample.FromType(HKQuantityType.Create(HKQuantityTypeIdentifier.DistanceWalkingRunning), this.TotalDistanceQuantity(), startDate, endDate); // add samples to workout this.healthStore.AddSamples(new HKSample[] { totalEnergyBurnedSample, totalDistanceSample }, workout, (isSuccess, error) => { if (isSuccess) { DispatchQueue.MainQueue.DispatchAsync(() => { WKInterfaceController.ReloadRootPageControllers(new string[] { nameof(SummaryInterfaceController) }, new NSObject[] { workout }, WKPageOrientation.Vertical, 0); }); } else { Console.WriteLine($"Adding workout subsamples failed with error: ({error?.Description ?? "unknown"})"); } }); // finish the route with a syn identifier so we can easily update the route later var objects = new NSObject[] { new NSString(new NSUuid().AsString()), NSNumber.FromInt32(1) }; var keys = new NSString[] { HKMetadataKey.SyncIdentifier, HKMetadataKey.SyncVersion }; var dictionary = NSDictionary.FromObjectsAndKeys(objects, keys); var metadata = new HKMetadata(dictionary); this.workoutRouteBuilder?.FinishRoute(workout, metadata, (workoutRoute, error) => { if (workoutRoute == null) { Console.WriteLine($"Finishing route failed with error: ({error?.Description ?? "unknown"})"); } }); }
/* * public async Task<bool> SaveBmi(double value, DateTime start, DateTime? end) * { * return await WriteAsync(HealthDataType.iOS_BodyMassIndex, value, start, end); * } * * public async Task<bool> SaveMindfulSession(int value, DateTime start, DateTime? end) * { * return await WriteAsync(HealthDataType.MindfulSession, value, start, end); * } * * public async Task<bool> SaveHeight(double value, DateTime start, DateTime? end) * { * return await WriteAsync(HealthDataType.Height, value, start, end); * } * * public async Task<bool> SaveWeight(double value, DateTime start, DateTime? end) * { * return await WriteAsync(HealthDataType.Weight, value, start, end); * } * * public async Task<bool> SaveStep(int value, DateTime start, DateTime? end) * { * return await WriteAsync(HealthDataType.StepCount, value, start, end); * } * * public async Task<bool> SaveSleepAnalysis(HKCategoryValueSleepAnalysis value, DateTime start, DateTime end) * { * return await WriteAsync(HealthDataType.SleepAnalysis, (int)value, start, end); * } */ public override async Task <bool> WriteAsync(WorkoutDataType workoutDataType, double calories, DateTime start, DateTime?end = null, string name = null) { var totalEnergyBurned = HKQuantity.FromQuantity(HKUnit.CreateJouleUnit(HKMetricPrefix.Kilo), 20); var metadata = new HKMetadata(); if (name != null) { metadata.WorkoutBrandName = name; } var workout = HKWorkout.Create(Convert(workoutDataType), (NSDate)start, (NSDate)end, new HKWorkoutEvent[] { }, totalEnergyBurned, null, metadata); var(success, error) = await _healthStore.SaveObjectAsync(workout); return(success); }
private void UpdateWorkoutLocationsRoute(HKWorkout workout, HKWorkoutRoute route, List <CLLocation> newLocations) { // create a workout route builder var workoutRouteBuilder = new HKWorkoutRouteBuilder(this.healthStore, null); // insert updated route locations workoutRouteBuilder.InsertRouteData(newLocations.ToArray(), (success, error) => { if (success) { var syncIdentifier = route.Metadata?.SyncIdentifier; if (!string.IsNullOrEmpty(syncIdentifier)) { // new metadata with the same sync identifier and a higher version var objects = new NSObject[] { new NSString(syncIdentifier), NSNumber.FromInt32(2) }; var keys = new NSString[] { HKMetadataKey.SyncIdentifier, HKMetadataKey.SyncVersion }; var dictionary = NSDictionary.FromObjectsAndKeys(objects, keys); var metadata = new HKMetadata(dictionary); // finish the route with updated metadata workoutRouteBuilder.FinishRoute(workout, metadata, (workoutRoute, routeRrror) => { if (workoutRoute != null) { Console.WriteLine($"Workout route updated: ({route})"); } else { Console.WriteLine($"An error occurred while finishing the new route: ({error?.LocalizedDescription ?? "Unknown"})"); } }); } else { throw new ArgumentNullException(nameof(syncIdentifier), "Missing expected sync identifier on route"); } } else { Console.WriteLine($"An error occurred while inserting route data ({error?.LocalizedDescription ?? "Unknown"})"); } }); }
public Task <ExerciseData> AddExercise(ExerciseData data) { var completionSource = new TaskCompletionSource <ExerciseData>(); var metadata = new HKMetadata() { GroupFitness = true, IndoorWorkout = true, CoachedWorkout = true, }; if (data.Time.TotalMinutes == 0) { DateTime start = ((DateTime)data.DateInit).ToLocalTime(); DateTime end = ((DateTime)data.DateEnd).ToLocalTime(); data.Time = end.Subtract(start); } HKQuantity calories = getCaloriesFromData(data); HKWorkout workOut = HKWorkout.Create(HKWorkoutActivityType.TraditionalStrengthTraining, data.DateInit, data.DateEnd, null, calories, null, metadata); HealthStore.SaveObject(workOut, (succes, error) => { if (succes) { data.Kilocalories = calories.GetDoubleValue(HKUnit.Kilocalorie); completionSource.SetResult(data); } else { completionSource.SetResult(null); } }); return(completionSource.Task); }
public static Workout ParseWorkout(HKWorkout workout) { var startDate = workout.StartDate.ToInstant(); var endDate = workout.EndDate.ToInstant(); return(new Workout { WorkoutType = workout.WorkoutActivityType.ToString(), SourceName = workout.Source.Name, EndDate = endDate, StartDate = startDate, Duration = Duration.FromSeconds(workout.Duration), Distance = workout.TotalDistance.Apply(Optional).Match( Some: d => Length.FromMeters(workout.TotalDistance.GetDoubleValue(HKUnit.Meter)), None: () => Length.Zero), Energy = workout.TotalEnergyBurned.Apply(Optional).Match( Some: e => Energy.FromCalories(workout.TotalEnergyBurned.GetDoubleValue(HKUnit.Calorie)), None: () => Energy.Zero), Device = workout.Device?.Name ?? "<no device>", }); }