Cómo integrar healthkit en un proyecto de xamarin - parte ii

logo_bravent_fondo_verde.jpg

Escrito por
12 marzo, 2018

¡Hello world! 

El otro día os contábamos qué es HealthKit y qué pasos hay que dar para empezar a crear un proyecto de Xamarin con ella. Si no lo recordáis o aún no lo habéis leído, tan solo tenéis que hacerclic aquí. 

Bien, pues hoy venimos con la segunda parte, en la que aprenderemos a introducir los datos en nuestra app y a realizar la lectura y la escritura de estos datos. 

¡Esperamos que os guste! 

  • PERMISOS: 

Vamos a comenzar introduciendo datos en nuestra app. Será una aplicación simple que incluirá: 

- Una pantalla con un cuadro de texto y un botón para introducir la frecuencia cardiaca
- Un label que mostrará la altura introducida en la app de Salud de iOS, mediante un segundo botón. 

healthkit8.pngLo primero que tenemos que hacer es pedir los permisos de lectura y escritura de HealthKit de la siguiente manera: 
En primer lugar tenemos que añadir a nuestra clase HealthKit haciendo un using de la misma, crearemos un objeto de tipo "HKHealthStore" y lo inicializaremos. Este objeto es el que nos va a dar acceso a todo el almacenamiento (tanto escritura como lectura). 

En nuestro ViewDidLoad, vamos a llamar al siguiente método: 

private void ValidateAuthorization()
        {
            var heartRateType =   HKQuantityType.Create(HKQuantityTypeIdentifier.HeartRate);
            var heightRateType = HKQuantityType.Create(HKQuantityTypeIdentifier.Height);

            var typesToWrite = new NSSet(new[] { heartRateType });
            var typesToRead = new NSSet(new []{heightRateType});
            healthKitStore.RequestAuthorizationToShare(
                    typesToWrite,
                    typesToRead,
                    ReactToHealthCarePermissions);
        }

En este método se realiza lo siguiente: 
- Se crean dos tipos de datos que son a los que vamos a pedir acceso
- Crearemos dos array, uno por cada una de las acciones que vamos a realizar en HealthKit (lectura y escritura). 
- Por último, llamaremos al método para pedir permisos de HealthKit. (Este solo se lanza si NO se ha lanzado previamente) y añadiremos el siguiente método para saber cuál es el resultado de la petición. 

void ReactToHealthCarePermissions(bool success, NSError error)
        {
            var access = healthKitStore.GetAuthorizationStatus(HKQuantityType.Create(HKQuantityTypeIdentifier.HeartRate));
            if (access.HasFlag(HKAuthorizationStatus.SharingAuthorized))
            {
                accesToHealth = true;
            }
            else
            {
                accesToHealth = false;
            }
        }

 

En este método simplemente guardaremos en un bool el resultado. 
NOTA: Una vez denegados los permisos, no podemos volver a pedirlos. Tiene que ser el usuario el que se dirija a la app de Salud y dé permisos
¡Y voilá! Ya tenemos preparada la app para pedir los permisos en el momento que se lance la app mediante esta pantalla (nativa):

healthkit9.png

  • LECTURA Y ESCRITURA DE DATOS: 

Para este apartado vamos a utilizar una clase que nos va a ayudar a realizar estos procedimientos. 
Esta clase tendrá los siguientes métodos: 

  • GetHeight: Este método es el que va a leer los datos de HealthKit y devolver en una Task el string que tenemos que mostrar al usuario. 

En primer lugar, necesitamos el tipo de información que vamos a leer y el string que vamos a devolver con el Task. 
Una vez hecho esto, se llama a FetchMostRecentData. Este método recibe el tipo de datos y los días que queremos consultar, nos devolverá un objeto tipo error y una lista de valores: 

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(DateTimeToNSDate(endDay), 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);
        }

 

Este método vale para cualquier dato que queramos leer de HealthKit siempre y cuando tengamos permisos, si no, devolverá siempre un error. 
En caso de que el error esté completado, a la Task le seteamos el error. En caso contrario, como solo queremos un dato que es el último introducido, y en los días solo le hemos pedido un día (el último), la lista puede venir vacía porque no hay datos o con un elemento que es el día de hoy. Por tanto, devolveremos el campo "Quantity" que incluye la unidad de medida: 

public Task <string> GetHeight(){

            var HeightType = HKQuantityType.Create(HKQuantityTypeIdentifier.Height);
            string Height = "0";
            var completionSource = new TaskCompletionSource<string>();           
            FetchMostRecentData(HeightType, (QuantityResults, error) =>
            {
                if (error != null)
                {
                    Height = "ERROR";
                }
                if (QuantityResults != null)
                {
                    if (QuantityResults.Count==0)
                    {
                        Height = "No tienes altura introducida";
                    }
                    results = QuantityResults;
                    for (int i = 0; i < QuantityResults.Count; i++)
                    {
                        Height = ((HKQuantitySample)QuantityResults[i]).Quantity.ToString();
                    }
                } completionSource.SetResult(Height);
            }, 1
            );
            return completionSource.Task;
        }

 

  • StoreHeartRate: 

Con este método vamos a guardar información que introducimos en la vista, recibe un double
En primer lugar, crearemos una unidad de medida que en este caso son minutos. Con esta unidad creamos la cantidad junto a el double recibido y un task para devolver el resultado. 

Acto seguido, crearemos el ID de registro, su tipo de datos y todo esto lo metemos en un contenedor tipo HKQuantitySample. 
Con todos los datos creados, los enviaremos a HealthKit con el evento SaveObject al que le pasamos el Sample anterior. 
Mandaremos el resultado de la escritura en un boleando de vuelta al controlador: 

public Task<bool> StoreHeartRate(double bpm)

        {
            var heartRateUnitType = HKUnit.Count.UnitDividedBy(HKUnit.Minute);
            var quantity = HKQuantity.FromQuantity(heartRateUnitType, bpm);
            var completionSource = new TaskCompletionSource<bool>(); 

            var heartRateId = HKQuantityTypeIdentifierKey.HeartRate;
            var heartRateQuantityType = HKQuantityType.GetQuantityType(heartRateId);
            var heartRateSample = HKQuantitySample.FromType(heartRateQuantityType, quantity, new NSDate(), new NSDate(), new HKMetadata()); 

            using (var healthKitStore = new HKHealthStore())

            {

                healthKitStore.SaveObject(heartRateSample, (success, error) => {
                    if (success)
                    {
                        completionSource.SetResult(true);
                    }

                    else
                    {
                        completionSource.SetResult(false);
                    }
                });
            }
            return completionSource.Task;
        }

 

Todo el ejemplo está recogido en nuestro GitHub, haz clic aquí si quieres verlo. 

¡Hasta aquí todo por hoy! 

Esperamos que os haya gustado el post, y ¡recordad! Si os apasiona el mundo del IoT, no os podéis perder nuestro próximo webinar: "Desarrollo de apps .NET Core con Raspberry Pi". 

¡A apuntarse! :) 

Webinar Raspberry Pi

ojo_07 ¿ Te gusta lo que lees? Suscríbete a nuestras newsletters