Exemple #1
0
        protected override async Task <IEnumerable <T> > Query <T>(HealthDataType healthDataType,
                                                                   AggregateTime aggregateTime,
                                                                   DateTime startDate, DateTime endDate)
        {
            var authorized = _healthService.HasOAuthPermission(_healthService.FitnessReadOptions(new HealthDataType[] { healthDataType }));

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

            var  fitData   = healthDataType.ToGoogleFit();
            long startTime = startDate.ToJavaTimeStamp();
            long endTime   = endDate.ToJavaTimeStamp();

            var readBuilder = new DataReadRequest.Builder()
                              .SetTimeRange(startTime, endTime, TimeUnit.Milliseconds)
                              .EnableServerQueries();

            if (aggregateTime != AggregateTime.None)
            {
                readBuilder.Aggregate(fitData.TypeIdentifier, fitData.AggregateType);

                switch (aggregateTime)
                {
                case AggregateTime.Year:
                    readBuilder.BucketByTime(365, TimeUnit.Days);
                    break;

                case AggregateTime.Month:
                    readBuilder.BucketByTime(31, TimeUnit.Days);
                    break;

                case AggregateTime.Week:
                    readBuilder.BucketByTime(7, TimeUnit.Days);
                    break;

                case AggregateTime.Day:
                    readBuilder.BucketByTime(1, TimeUnit.Days);
                    break;

                case AggregateTime.Hour:
                    readBuilder.BucketByTime(1, TimeUnit.Hours);
                    break;
                }
            }
            else
            {
                readBuilder.Read(fitData.TypeIdentifier);
            }

            var readRequest = readBuilder.Build();

            var response = await FitnessClass.GetHistoryClient(_currentActivity, GoogleSignIn.GetLastSignedInAccount(_currentActivity))
                           .ReadDataAsync(readRequest).ConfigureAwait(false);

            double valueToSubstract = 0;

            if (healthDataType == HealthDataType.CaloriesActive)
            {
                valueToSubstract = await GetBasalAvg(endDate);
            }

            if (response == null)
            {
                return(new List <T>());
            }

            if (response.Buckets.Any())
            {
                var output = new List <T>();
                foreach (var bucket in response.Buckets)
                {
                    var dataSet = bucket.GetDataSet(fitData.AggregateType);
                    output.AddRange((IEnumerable <T>)dataSet.DataPoints.Select(result =>
                                                                               CreateAggregatedData(result, fitData, valueToSubstract)));

                    if (!dataSet.DataPoints.Any() && healthDataType == HealthDataType.Droid_BasalMetabolicRate)
                    {
                        output.Add(
                            new AggregatedHealthData()
                        {
                            StartDate = bucket.GetStartTime(TimeUnit.Milliseconds).ToDateTime(),
                            EndDate   = bucket.GetEndTime(TimeUnit.Milliseconds).ToDateTime(),
                            Sum       = valueToSubstract
                        } as T);
                    }
                }

                return(output);
            }

            return((IEnumerable <T>)response.GetDataSet(fitData.TypeIdentifier)?.DataPoints?
                   .Select(dataPoint => new HealthData
            {
                StartDate = dataPoint.GetStartTime(TimeUnit.Milliseconds).ToDateTime(),
                EndDate = dataPoint.GetEndTime(TimeUnit.Milliseconds).ToDateTime(),
                Value = ReadValue(dataPoint, fitData.Unit, valueToSubstract) ?? 0,
                UserEntered = dataPoint.OriginalDataSource?.StreamName == "user_input"
            }).ToList());
        }
        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);
        }
        private IReadOnlyDictionary <HealthDataType, Task <IEnumerable <T> > > FetchData <T>(AggregateTime aggregateTime, params HealthDataType[] healthDataTypes) where T : class, IHealthData
        {
            if (healthDataTypes == null || healthDataTypes.Length == 0)
            {
                throw new InvalidOperationException("No DataTypes specified! Please use .AddDataType before calling .FetchDataAsync");
            }

            var dic = healthDataTypes.ToDictionary(dataType => dataType,
                                                   dataType => Query <T>(dataType, aggregateTime, _startDate, _endDate));

            return(new ReadOnlyDictionary <HealthDataType, Task <IEnumerable <T> > >(dic));
        }
 protected abstract Task <IEnumerable <T> > Query <T>(HealthDataType dataTypes,
                                                      AggregateTime aggregateTime,
                                                      DateTime startDate, DateTime endDate) where T : class, IHealthData;
 public IReadOnlyDictionary <HealthDataType, Task <IEnumerable <AggregatedHealthData> > > ReadAggregate(AggregateTime aggregateTime, params HealthDataType[] healthDataTypes)
 {
     return(FetchData <AggregatedHealthData>(aggregateTime, healthDataTypes));
 }