Esempio n. 1
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 iOSHealthKitFlightsClimbedProbe()
     : base(HKQuantityType.Create(HKQuantityTypeIdentifier.FlightsClimbed))
 {
 }
 public iOSHealthKitDistanceWalkingRunningProbe()
     : base(HKQuantityType.Create(HKQuantityTypeIdentifier.DistanceWalkingRunning))
 {
 }
Esempio n. 4
0
        public void EnumValues_22351()
        {
            TestRuntime.AssertXcodeVersion(6, 0);

            foreach (HKQuantityTypeIdentifier value in Enum.GetValues(typeof(HKQuantityTypeIdentifier)))
            {
                // we need to have version checks for anything added after iOS 8.0
                switch (value)
                {
                case HKQuantityTypeIdentifier.BasalBodyTemperature:
                case HKQuantityTypeIdentifier.DietaryWater:
                case HKQuantityTypeIdentifier.UVExposure:
                    if (!TestRuntime.CheckXcodeVersion(7, 0))
                    {
                        continue;
                    }
                    break;

                case HKQuantityTypeIdentifier.AppleExerciseTime:
                    if (!TestRuntime.CheckXcodeVersion(7, 3))
                    {
                        continue;
                    }
                    break;

                case HKQuantityTypeIdentifier.DistanceWheelchair:
                case HKQuantityTypeIdentifier.PushCount:
                case HKQuantityTypeIdentifier.DistanceSwimming:
                case HKQuantityTypeIdentifier.SwimmingStrokeCount:
                    if (!TestRuntime.CheckXcodeVersion(8, 0))
                    {
                        continue;
                    }
                    break;

                case HKQuantityTypeIdentifier.WaistCircumference:
                case HKQuantityTypeIdentifier.VO2Max:
                case HKQuantityTypeIdentifier.InsulinDelivery:
                case HKQuantityTypeIdentifier.RestingHeartRate:
                case HKQuantityTypeIdentifier.WalkingHeartRateAverage:
                case HKQuantityTypeIdentifier.HeartRateVariabilitySdnn:
                    if (!TestRuntime.CheckXcodeVersion(9, 0))
                    {
                        continue;
                    }
                    break;

                case HKQuantityTypeIdentifier.DistanceDownhillSnowSports:
                    if (!TestRuntime.CheckXcodeVersion(9, 2))
                    {
                        continue;
                    }
                    break;

                case HKQuantityTypeIdentifier.AppleStandTime:
                case HKQuantityTypeIdentifier.EnvironmentalAudioExposure:
                case HKQuantityTypeIdentifier.HeadphoneAudioExposure:
                    if (!TestRuntime.CheckXcodeVersion(11, 0))
                    {
                        continue;
                    }
                    break;

                case HKQuantityTypeIdentifier.SixMinuteWalkTestDistance:
                case HKQuantityTypeIdentifier.StairAscentSpeed:
                case HKQuantityTypeIdentifier.StairDescentSpeed:
                case HKQuantityTypeIdentifier.WalkingAsymmetryPercentage:
                case HKQuantityTypeIdentifier.WalkingDoubleSupportPercentage:
                case HKQuantityTypeIdentifier.WalkingSpeed:
                case HKQuantityTypeIdentifier.WalkingStepLength:
                    if (!TestRuntime.CheckXcodeVersion(12, TestRuntime.MinorXcode12APIMismatch))
                    {
                        continue;
                    }
                    break;
                }

                try {
                    using (var ct = HKQuantityType.Create(value)) {
                        Assert.That(ct.Handle, Is.Not.EqualTo(IntPtr.Zero), value.ToString());
                    }
                }
                catch (Exception e) {
                    Assert.Fail("{0} could not be created: {1}", value, e);
                }
            }
        }
Esempio n. 5
0
 public iOSHealthKitWeightProbe()
     : base(HKQuantityType.Create(HKQuantityTypeIdentifier.BodyMass))
 {
 }
 public iOSHealthKitHeightProbe()
     : base(HKQuantityType.Create(HKQuantityTypeIdentifier.Height))
 {
 }
Esempio n. 7
0
 public HealthKitData(HKQuantityTypeIdentifier identifier)
 {
     HKType = HKTypes.Quantity;
     QuantityTypeIdentifier = identifier;
     Permission             = HKQuantityType.Create(identifier);
 }
Esempio n. 8
0
 public iOSHealthKitStepCountProbe()
     : base(HKQuantityType.Create(HKQuantityTypeIdentifier.StepCount))
 {
 }
 public iOSHealthKitHeartRateProbe()
     : base(HKQuantityType.Create(HKQuantityTypeIdentifier.HeartRate))
 {
 }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        public void SaveWorkout()
        {
            // Obtain the `HKObjectType` for active energy burned.
            var activeEnergyType = HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned);

            if (activeEnergyType == null)
            {
                return;
            }

            // Obtain the `HKObjectType` for HeartRate.
            var heartRateType = HKQuantityType.Create(HKQuantityTypeIdentifier.HeartRate);

            if (heartRateType == 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.Meter, 0.0),
                                           metadata);

            var finalActiveEnergySamples = ActiveEnergySamples;
            var finalHeartRateSamples    = HeartRateSamples;

            if (HealthStore.GetAuthorizationStatus(activeEnergyType) != HKAuthorizationStatus.SharingAuthorized ||
                HealthStore.GetAuthorizationStatus(heartRateType) != 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()}.");
                        }
                    });
                }
                if (finalHeartRateSamples.Count > 0)
                {
                    HealthStore.AddSamples(finalHeartRateSamples.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()}.");
                        }
                    });
                }
            });
        }
Esempio n. 12
0
        public override void WillActivate()
        {
            base.WillActivate();
            ResetUI();
            if (!HKHealthStore.IsHealthDataAvailable)
            {
                return;
            }
            // We need to be able to write workouts, so they display as a standalone workout in the Activity app on iPhone.
            // We also need to be able to write Active Energy Burned to write samples to HealthKit to later associating with our app.

            var typesToShare = new NSSet(HKQuantityType.Create(HKQuantityTypeIdentifier.HeartRate), HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned), HKObjectType.GetWorkoutType());
            var typesToRead  = new NSSet(HKQuantityType.Create(HKQuantityTypeIdentifier.HeartRate), HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned));

            HealthStore.RequestAuthorizationToShare(typesToShare, typesToRead, (bool success, NSError error) =>
            {
                if (error != null && !success)
                {
                    Console.WriteLine("You didn't allow HealthKit to access these read/write data types. " +
                                      "In your app, try to handle this error gracefully when a user decides not to provide access. " +
                                      $"The error was: {error.LocalizedDescription}. If you're using a simulator, try it on a device.");
                }
            });
            _dangerousHeartRate.Where(v => v > 30.0).Subscribe(
                v => SessionManager.SharedManager.UpdateApplicationContext(
                    new Dictionary <string, object>()
            {
                { "HeartRate", v.ToString() }
            }));
        }
Esempio n. 13
0
        private void ValidateAuthorization()
        {
            var typesToShare = new NSSet(HKQuantityType.Create(HKQuantityTypeIdentifier.HeartRate), HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned), HKObjectType.GetWorkoutType());
            var typesToRead  = new NSSet(HKQuantityType.Create(HKQuantityTypeIdentifier.HeartRate), HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned));

            _healthStore.RequestAuthorizationToShare(
                typesToShare,
                typesToRead,
                ReactToHealthCarePermissions);
        }
 public iOSHealthKitNumberOfTimesFallenProbe()
     : base(HKQuantityType.Create(HKQuantityTypeIdentifier.NumberOfTimesFallen))
 {
 }