Beispiel #1
0
        private async Task DeleteSamples(Measure measure)
        {
            if (_suppressed)
            {
                return;
            }

            var predicate = HKQuery.GetPredicateForMetadataKey(
                HKMetadataKey.ExternalUuid,
                new[] { NSObject.FromObject(MetadataKey.GetExternalUUID(measure.Id)) });

            var result = await _healthStore.DeleteObjectsAsync(
                HKQuantityType.Create(HKQuantityTypeIdentifier.BloodGlucose),
                predicate);

            if (!result.Item1)
            {
                _log.Warn($"Can't delete blood glucose data by reason: {result.Item2.LocalizedDescription}");
            }

            result = await _healthStore.DeleteObjectsAsync(
                HKQuantityType.Create(HKQuantityTypeIdentifier.InsulinDelivery),
                predicate);

            if (!result.Item1)
            {
                _log.Warn($"Can't delete insulin data by reason: {result.Item2.LocalizedDescription}");
            }
        }
        public void FetchSteps(Action <double> completionHandler)
        {
            var calendar          = NSCalendar.CurrentCalendar;
            var startDate         = DateTime.Today;
            var endDate           = DateTime.Now;
            var stepsQuantityType = HKQuantityType.Create(HKQuantityTypeIdentifier.StepCount);

            var predicate = HKQuery.GetPredicateForSamples((NSDate)startDate, (NSDate)endDate, HKQueryOptions.StrictStartDate);

            var query = new HKStatisticsQuery(stepsQuantityType, predicate, HKStatisticsOptions.CumulativeSum,
                                              (HKStatisticsQuery resultQuery, HKStatistics results, NSError error) =>
            {
                if (error != null && completionHandler != null)
                {
                    completionHandler(0.0f);
                }

                var totalSteps = results.SumQuantity();
                if (totalSteps == null)
                {
                    totalSteps = HKQuantity.FromQuantity(HKUnit.Count, 0.0);
                }

                completionHandler(totalSteps.GetDoubleValue(HKUnit.Count));
            });

            HealthStore.ExecuteQuery(query);
        }
        void UpdateJournal(object sender, EventArgs args)
        {
            var calendar = NSCalendar.CurrentCalendar;

            var startDate = DateTime.Now.Date;
            var endDate   = startDate.AddDays(1);

            var sampleType = HKSampleType.GetQuantityType(HKQuantityTypeIdentifierKey.DietaryEnergyConsumed);
            var predicate  = HKQuery.GetPredicateForSamples((NSDate)startDate, (NSDate)endDate, HKQueryOptions.None);

            var query = new HKSampleQuery(sampleType, predicate, 0, new NSSortDescriptor[0], (resultQuery, results, error) => {
                if (error != null)
                {
                    Console.WriteLine("An error occured fetching the user's tracked food. " +
                                      "In your app, try to handle this gracefully. The error was: {0}.", error.LocalizedDescription);
                    return;
                }

                InvokeOnMainThread(() => {
                    FoodItems.RemoveAllObjects();
                    foreach (HKQuantitySample sample in results)
                    {
                        var foodName  = (NSString)sample.Metadata.Dictionary [HKMetadataKey.FoodType];
                        double joules = sample.Quantity.GetDoubleValue(HKUnit.Joule);
                        var foodItem  = FoodItem.Create(foodName, joules);

                        FoodItems.Add(foodItem);
                    }

                    TableView.ReloadData();
                });
            });

            HealthStore.ExecuteQuery(query);
        }
        public void FetchMetersWalked(Action <double> completionHandler)
        {
            var calendar          = NSCalendar.CurrentCalendar;
            var startDate         = DateTime.Today;
            var endDate           = DateTime.Now;
            var stepsQuantityType = HKQuantityType.Create(HKQuantityTypeIdentifier.DistanceWalkingRunning);

            var predicate = HKQuery.GetPredicateForSamples((NSDate)startDate, (NSDate)endDate, HKQueryOptions.StrictStartDate);

            var query = new HKStatisticsQuery(stepsQuantityType, predicate, HKStatisticsOptions.CumulativeSum,
                                              (HKStatisticsQuery resultQuery, HKStatistics results, NSError error) =>
            {
                if (error != null && completionHandler != null)
                {
                    completionHandler(0);
                }

                var distance = results.SumQuantity();
                if (distance == null)
                {
                    distance = HKQuantity.FromQuantity(HKUnit.Meter, 0);
                }

                completionHandler(distance.GetDoubleValue(HKUnit.Meter));
            });

            HealthStore.ExecuteQuery(query);
        }
        void FetchMostRecentData(Action <double, NSError> completionHandler)
        {
            var calendar  = NSCalendar.CurrentCalendar;
            var startDate = DateTime.Now.Date;
            var endDate   = startDate.AddDays(1);

            var sampleType = HKQuantityType.GetQuantityType(HKQuantityTypeIdentifierKey.DietaryEnergyConsumed);
            var predicate  = HKQuery.GetPredicateForSamples((NSDate)startDate, (NSDate)endDate, HKQueryOptions.StrictStartDate);

            var query = new HKStatisticsQuery(sampleType, predicate, HKStatisticsOptions.CumulativeSum,
                                              (HKStatisticsQuery resultQuery, HKStatistics results, NSError error) => {
                if (error != null && completionHandler != null)
                {
                    completionHandler(0.0f, error);
                }

                var totalCalories = results.SumQuantity();
                if (totalCalories == null)
                {
                    totalCalories = HKQuantity.FromQuantity(HKUnit.Joule, 0.0);
                }

                if (completionHandler != null)
                {
                    completionHandler(totalCalories.GetDoubleValue(HKUnit.Joule), error);
                }
            });

            HealthStore.ExecuteQuery(query);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        private void LoadWorkouts(Action <List <HKWorkout> > completion)
        {
            var workoutType = HKObjectType.GetWorkoutType();
            var predicate   = HKQuery.GetPredicateForObjectsFromSource(HKSource.GetDefaultSource);
            var query       = new HKSampleQuery(workoutType, predicate, HKSampleQuery.NoLimit, null, (sender, results, error) =>
            {
                var isSuccess = results != null;
                if (isSuccess)
                {
                    var workouts = results.OfType <HKWorkout>().ToList();
                    isSuccess    = workouts.Any();
                    if (isSuccess)
                    {
                        completion(workouts);
                    }
                }

                if (!isSuccess)
                {
                    Console.WriteLine($"An error occurred: ({error?.LocalizedDescription ?? "Unknown"})");
                }
            });

            this.healthStore.ExecuteQuery(query);
        }
        private void StartQuery(HKQuantityTypeIdentifier quantityTypeIdentifier, NSDate startDate, HKAnchoredObjectUpdateHandler handler)
        {
            var datePredicate   = HKQuery.GetPredicateForSamples(startDate, null, HKQueryOptions.StrictStartDate);
            var devicePredicate = HKQuery.GetPredicateForObjectsFromDevices(new NSSet <HKDevice>(HKDevice.LocalDevice));
            var queryPredicate  = NSCompoundPredicate.CreateAndPredicate(new NSPredicate[] { datePredicate, devicePredicate });

            var quantityType = HKQuantityType.Create(quantityTypeIdentifier);
            var query        = new HKAnchoredObjectQuery(quantityType, queryPredicate, null, HKSampleQuery.NoLimit, handler);

            query.UpdateHandler = handler;
            this.healthStore.ExecuteQuery(query);

            this.activeDataQueries.Add(query);
        }
        private void FetchMostRecentData(HKQuantityType quantityType, Action <List <HKSample>, NSError> completion, int days)
        {
            var      timeSortDescriptor = new NSSortDescriptor(HKSample.SortIdentifierEndDate, false);
            DateTime startDay           = DateTime.Now;
            DateTime endDay             = startDay.AddDays(-days).AddHours(-startDay.Hour).AddMinutes(-startDay.Minute).AddSeconds(-startDay.Second).AddMilliseconds(-startDay.Millisecond);
            var      predicate          = HKQuery.GetPredicateForSamples(DateUtil.DateTimeToNSDate(endDay), DateUtil.DateTimeToNSDate(startDay), HKQueryOptions.None);
            var      query = new HKSampleQuery(quantityType, predicate, 0, new NSSortDescriptor[] { timeSortDescriptor },
                                               (HKSampleQuery resultQuery, HKSample[] results, NSError error) =>
            {
                if (completion != null && error != null)
                {
                    completion(null, error);
                    return;
                }

                completion?.Invoke(results.ToList(), error);
            });

            HealthStore.ExecuteQuery(query);
        }
        public int StepQuery()
        {
            var dateComponents = new NSDateComponents();

            dateComponents.Day = -1;
            var cal       = new NSCalendar(NSCalendarType.ISO8601);
            var yesterday = cal.DateFromComponents(dateComponents);
            var predicate = HKQuery.GetPredicateForSamples(yesterday, new NSDate(), HKQueryOptions.None);
            var query     = new HKSampleQuery(HKObjectType.GetQuantityType(HKQuantityTypeIdentifierKey.StepCount),
                                              predicate,
                                              0,
                                              null,
                                              new HKSampleQueryResultsHandler((retQuery, results, error) => {
                Console.WriteLine(results.Length);
            }));

            _healthStore.ExecuteQuery(query);

            return(0);
        }
Beispiel #11
0
        private async Task EditMeasure(Measure measure)
        {
            if (_suppressed)
            {
                return;
            }

            if (!measure.Level.HasValue)
            {
                var predicate = HKQuery.GetPredicateForMetadataKey(
                    HKMetadataKey.ExternalUuid,
                    new[] { NSObject.FromObject(MetadataKey.GetExternalUUID(measure.Id)) });

                await _healthStore.DeleteObjectsAsync(
                    HKQuantityType.Create(HKQuantityTypeIdentifier.BloodGlucose),
                    predicate);
            }

            var samples = GetQuantitySamples(measure);

            await AddSamples(samples);
        }
Beispiel #12
0
        protected override Task <IEnumerable <T> > Query <T>(HealthDataType healthDataType,
                                                             AggregateTime aggregateTime,
                                                             DateTime startDate, DateTime endDate)
        {
            if (_healthStore == null || !HKHealthStore.IsHealthDataAvailable)
            {
                throw new NotSupportedException("HealthKit data is not available on this device");
            }

            var authorized = IsAuthorizedToRead(healthDataType);

            if (!authorized)
            {
                throw new UnauthorizedAccessException($"Not enough permissions to request {healthDataType}");
            }

            var taskComplSrc  = new TaskCompletionSource <IEnumerable <T> >();
            var healthKitType = healthDataType.ToHealthKit();
            var quantityType  = HKQuantityType.Create(healthKitType.QuantityTypeIdentifier);
            var predicate     = HKQuery.GetPredicateForSamples((NSDate)startDate, (NSDate)endDate, HKQueryOptions.StrictStartDate);

            if (aggregateTime != AggregateTime.None)
            {
                var anchor   = NSCalendar.CurrentCalendar.DateBySettingsHour(0, 0, 0, NSDate.Now, NSCalendarOptions.None);
                var interval = new NSDateComponents();

                switch (aggregateTime)
                {
                case AggregateTime.Year:
                    interval.Year = 1;
                    break;

                case AggregateTime.Month:
                    interval.Month = 1;
                    break;

                case AggregateTime.Week:
                    interval.Week = 1;
                    break;

                case AggregateTime.Day:
                    interval.Day = 1;
                    break;

                case AggregateTime.Hour:
                    interval.Hour = 1;
                    break;
                }

                HKStatisticsOptions hkStatisticsOptions;

                if (healthKitType.Cumulative)
                {
                    hkStatisticsOptions = HKStatisticsOptions.CumulativeSum;
                }
                else
                {
                    hkStatisticsOptions = HKStatisticsOptions.DiscreteAverage |
                                          HKStatisticsOptions.DiscreteMax |
                                          HKStatisticsOptions.DiscreteMax;
                }

                var queryAggregate = new HKStatisticsCollectionQuery(quantityType, predicate, hkStatisticsOptions,
                                                                     anchor, interval)
                {
                    InitialResultsHandler = (collectionQuery, results, error) =>
                    {
                        var healthData = new List <T>();

                        foreach (var result in results.Statistics)
                        {
                            var hData = new AggregatedHealthData
                            {
                                StartDate = (DateTime)result.StartDate,
                                EndDate   = (DateTime)result.EndDate,
                            };

                            if (healthKitType.Cumulative)
                            {
                                hData.Sum = result.SumQuantity().GetDoubleValue(healthKitType.Unit);
                            }
                            else
                            {
                                hData.Min     = result.MinimumQuantity().GetDoubleValue(healthKitType.Unit);
                                hData.Max     = result.MaximumQuantity().GetDoubleValue(healthKitType.Unit);
                                hData.Average = result.AverageQuantity().GetDoubleValue(healthKitType.Unit);
                            }

                            healthData.Add(hData as T);
                        }

                        taskComplSrc.SetResult(healthData);
                    }
                };

                _healthStore.ExecuteQuery(queryAggregate);
            }
            else
            {
                var sortDescriptor = new[] { new NSSortDescriptor(HKSample.SortIdentifierEndDate, true) };


                HKSampleType sampleType;

                if (healthKitType.HKType == HealthKitData.HKTypes.Category)
                {
                    sampleType = HKCategoryType.Create(healthKitType.CategoryTypeIdentifier);
                }
                else if (healthKitType.HKType == HealthKitData.HKTypes.Quantity)
                {
                    sampleType = HKQuantityType.Create(healthKitType.QuantityTypeIdentifier);
                }
                else if (healthKitType.HKType == HealthKitData.HKTypes.Workout)
                {
                    sampleType = HKSampleType.GetWorkoutType();
                }
                else
                {
                    throw new NotSupportedException();
                }

                var query = new HKSampleQuery(sampleType, predicate,
                                              HKSampleQuery.NoLimit, sortDescriptor,
                                              (resultQuery, results, error) =>
                {
                    IEnumerable <T> healthData = default(IEnumerable <T>);

                    if (sampleType == HKSampleType.GetWorkoutType())
                    {
                        healthData = results?.Select(result => new WorkoutData
                        {
                            StartDate   = (DateTime)result.StartDate,
                            EndDate     = (DateTime)result.EndDate,
                            Duration    = (result as HKWorkout).Duration,
                            Device      = (result as HKWorkout).Device?.ToString(),
                            WorkoutType = (result as HKWorkout).WorkoutDataType()
                                          //TotalDistance = Convert.ToDouble((result as HKWorkout).TotalDistance),
                                          //TotalEnergyBurned = Convert.ToDouble((result as HKWorkout).TotalEnergyBurned)
                        } as T);
                    }
                    else
                    {
                        healthData = results?.Select(result => new HealthData
                        {
                            StartDate   = (DateTime)result.StartDate,
                            EndDate     = (DateTime)result.EndDate,
                            Value       = ReadValue(result, healthKitType.Unit),
                            UserEntered = result.Metadata?.WasUserEntered ?? false,
                        } as T);
                    }



                    taskComplSrc.SetResult(healthData);
                });

                _healthStore.ExecuteQuery(query);
            }

            return(taskComplSrc.Task);
        }
        public void BeginWorkout(DateTime beginDate)
        {
            // Obtain the `HKObjectType` for active energy burned and the `HKUnit` for kilocalories.
            var activeEnergyType = HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned);

            if (activeEnergyType == null)
            {
                return;
            }

            var energyUnit = HKUnit.Kilocalorie;

            // Update properties.
            WorkoutBeginDate = beginDate;
            workoutButton.SetTitle("End Workout");

            // Set up a predicate to obtain only samples from the local device starting from `beginDate`.

            var datePredicate = HKQuery.GetPredicateForSamples((NSDate)beginDate, null, HKQueryOptions.None);

            var devices         = new NSSet <HKDevice> (new HKDevice[] { HKDevice.LocalDevice });
            var devicePredicate = HKQuery.GetPredicateForObjectsFromDevices(devices);
            var predicate       = NSCompoundPredicate.CreateAndPredicate(new NSPredicate[] { datePredicate, devicePredicate });

            //Create a results handler to recreate the samples generated by a query of active energy samples so that they can be associated with this app in the move graph.It should be noted that if your app has different heuristics for active energy burned you can generate your own quantities rather than rely on those from the watch.The sum of your sample's quantity values should equal the energy burned value provided for the workout
            Action <List <HKSample> > sampleHandler;

            sampleHandler = (List <HKSample> samples) => {
                DispatchQueue.MainQueue.DispatchAsync(delegate {
                    var accumulatedSamples = new List <HKQuantitySample> ();

                    var initialActivityEnergy = CurrentActiveEnergyQuantity.GetDoubleValue(energyUnit);
                    double accumulatedValue   = initialActivityEnergy;
                    foreach (HKQuantitySample sample in samples)
                    {
                        accumulatedValue = accumulatedValue + sample.Quantity.GetDoubleValue(energyUnit);
                        var ourSample    = HKQuantitySample.FromType(activeEnergyType, sample.Quantity, sample.StartDate, sample.EndDate);
                        accumulatedSamples.Add(ourSample);
                    }

                    // Update the UI.
                    CurrentActiveEnergyQuantity = HKQuantity.FromQuantity(energyUnit, accumulatedValue);
                    activeEnergyBurnedLabel.SetText($"{accumulatedValue}");

                    // Update our samples.
                    ActiveEnergySamples.AddRange(accumulatedSamples);
                });
            };

            // Create a query to report new Active Energy Burned samples to our app.
            var activeEnergyQuery = new HKAnchoredObjectQuery(activeEnergyType, predicate, null, HKSampleQuery.NoLimit, (query, addedObjects, deletedObjects, newAnchor, error) => {
                if (error == null)
                {
                    // NOTE: `deletedObjects` are not considered in the handler as there is no way to delete samples from the watch during a workout
                    ActiveEnergySamples = new List <HKSample>(addedObjects);
                    sampleHandler(ActiveEnergySamples);
                }
                else
                {
                    Console.WriteLine($"An error occured executing the query. In your app, try to handle this gracefully. The error was: {error}.");
                }
            });

            // Assign the same handler to process future samples generated while the query is still active.
            activeEnergyQuery.UpdateHandler = (query, addedObjects, deletedObjects, newAnchor, error) => {
                if (error == null)
                {
                    ActiveEnergySamples = new List <HKSample> (addedObjects);
                    sampleHandler(ActiveEnergySamples);
                }
                else
                {
                    Console.WriteLine($"An error occured executing the query. In your app, try to handle this gracefully. The error was: {error}.");
                }
            };

            // Start Query
            CurrentQuery = activeEnergyQuery;
            HealthStore.ExecuteQuery(activeEnergyQuery);
        }