Bonne année et ... bonne santé avec Google Fit !
Suite au développement d'une application sportive et à une conférence en interne. Je me suis rendu compte que les APIs Google Fit étaient très largement méconnues de la communauté des développeurs. Que peut-on faire avec Google Fit ? À quoi ça sert ? Est-ce vraiment utile ? Autant d'interrogations qui trouvent leurs réponses dans cet article. Avec Google Fit, Google propose un “Fitness Store” afin d’héberger et de centraliser toutes les données liées à la santé. Le but étant de créer une sorte de standard afin de pouvoir échanger des données facilement entre applications. Il permet ainsi de stocker tout type de données liées à l’activité physique, l’alimentation ainsi qu’à certaines données médicales. Google Fit est accessible sur Android mais aussi directement depuis le web c’est pourquoi Google met à disposition deux jeux d’APIs: REST et Android.
Cet article ce concentrera sur celles d'Android celles destinées au web restent tout aussi complètes.
1. API & Permissions
1.1 Une histoire de famille
Google Fit est accessible via sept familles d’APIs comme l’illustre la Figure 1:
FIGURE 1: Google Fit APIs
**HistoryApi**
: Permet de manipuler des données du “Fitness Store”(ex: insertions, suppressions, mises à jour). [Voir 3.1, 3.2].**RecordingApi**
: Permet de s’abonner à un type de donnée (ex: le nombre de pas de l’utilisateur) afin d’être prévenu en cas de changement.**SensorApi**
: Permet de lire les données brutes d’un capteur.**SessionApi**
: Permet de manipuler des sessions [Voir 3.3, 3.4].**BLE Api**
: Permet de communiquer avec des wearable devices et autres appareils bluetooth. Vous pourrez ensuite vous rediriger vers SensorApi pour collecter des données.**ConfigApi**
: Permet de créer des data types personnalisés [Voir 2.2].**GoalsApi**
: Permet d’accéder aux objectifs de votre utilisateur ainsi qu’à son taux d’achèvement. Il existe trois types d’objectifs durée, distance, nombre de calories.
1.2 Demander l’autorisation !
Google Fit manipule des données sensibles, ainsi avant de pouvoir pleinement exploiter les APIs il est nécessaire d’en demander l’autorisation à l’utilisateur.
Pour cela il faudra passer par un GoogleApiClient auquel on précise les APIs que l’on souhaite exploiter ainsi que leurs scopes (droits) associés.
ce qui devrait résulter en un dialog comme suit que l’utilisateur devra accepter:
FIGURE 2: Exemple d’autorisations
On remarque que l’utilisateur ne peut pas priver l’accès à certains types de données comme c’est par exemple le cas pour les permissions d’applications. Ici il doit autoriser l’accès à toutes ses données “Fitness” sans exception. Apple HealthKit permet par exemple de restreindre l’accès à certains types de données (âge, sexe, etc) tout en acceptant les autres.
2 - Un peu de théorie
2.1 - Les objets
Au sein de Google Fit que vous vouliez insérer de la nourriture, des exercices physiques ou autres vous utiliserez les six objets suivant:
- DataType
- DataSource
- DataPoint
- DataSet
- Session
FIGURE 3: Structure des objets
2.2 DataType & DataSource
Un datatype est généralement utilisé à la construction d’une datasource.
Google Fit vous fournit bon nombre de datatype par défaut afin de créer vos datasources et d’enrichir le “Fitness Store” de l’utilisateur. Ils sont regroupés en 5 catégories. Les données liées à une activité sportive (Activity), les données liées à une position (Location), les données liées à un état physique (Body) et enfin les données liées à l’alimentation (Nutrition). Nous les listons dans le tableau suivant:
Datatype | Permission Scope | Fields | Associated value |
com.google.activity.samples | Activity | activity (int—enum)<br><br>confidence (float—percent) | TYPE_ACTIVITY_SAMPLES |
com.google.activity.segment | Activity | activity (int—enum) | TYPE_ACTIVITY_SEGMENT |
com.google.calories.bmr | X | calories (float—kcal) | TYPE_BASAL_METABOLIC_RATE |
com.google.body.fat.percentage | X | body_mass (float—percent) | TYPE_BODY_FAT_PERCENTAGE |
com.google.calories.expended | Activity | calories (float—kcal) | TYPE_CALORIES_EXPENDED |
com.google.cycling.pedaling.cadence | Activity | rpm (float—rpm) | TYPE_CYCLING_PEDALING_CADENCE |
com.google.cycling.pedaling.cumulative | X | rpm (float—rpm) | TYPE_CYCLING_PEDALING_CUMULATIVE |
com.google.cycling.wheel_revolution.rpm | Location | rpm (float—rpm) | TYPE_CYCLING_WHEEL_REVOLUTION |
com.google.cycling.wheel.revolutions | X | rpm (float—rpm) | TYPE_CYCLING_WHEEL_RPM |
com.google.distance.delta | Location | distance (float—meters) | TYPE_DISTANCE_DELTA |
com.google.heart_rate.bpm | Body | bpm (float—bpm) | TYPE_HEART_RATE_BPM |
com.google.height | Body | height (float—meters) | TYPE_HEIGHT |
com.google.location.sample | Location | latitude (float—degrees)<br><br>longitude (float—degrees)<br><br>accuracy (float—meters)<br><br>altitude (float—meters) | TYPE_LOCATION_SAMPLE |
com.google.location.track | X | latitude (float—degrees)<br><br>longitude (float—degrees)<br><br>accuracy (float—meters)<br><br>altitude (float—meters) | TYPE_LOCATION_TRACK<br><br>(The difference between the two data types is that, while location.sample data points have an exact timestamp, location.track data points have an inexact time interval) |
com.google.nutrition | Nutrition | nutrients (Map<String, float>—calories/grams/IU) meal_type (int—enum)<br><br>food_item (String—n/a) | TYPE_NUTRITION |
com.google.hydration | Nutrition | field_volume(float-liters) | TYPE_HYDRATION |
com.google.power.sample | Activity | watts (float—watts) | TYPE_POWER_SAMPLE |
com.google.speed | Location | speed (float—m/s) | TYPE_SPEED |
com.google.step_count.cadence | Activity | rpm (float—steps/min) | TYPE_STEP_COUNT_CADENCE |
com.google.step_count.delta | Activity | steps (int—count) | TYPE_STEP_COUNT_DELTA |
com.google.weight | Body | weight (float—kg) | TYPE_WEIGHT |
com.google.activity.exercise | Activity | exercise (int—enum)<br><br>repetitions (int—count)<br><br>resistance type (int—enum)<br><br>resistance (float—kg)<br><br>duration (int—milliseconds) | TYPE_WORKOUT_EXERCISE |
X: No reference in scopes array
TABLE 1:DataType par défaut
Cependant certains types, nommés HealthDataType, vous seront interdits avant de vous être inscrits auprès de Google (vous pouvez en faire la demande à cette adresse google-fit-restricted@google.com). Ces données sont considérées comme trop sensibles pour y avoir accès par défaut.
De plus si vous utilisez un appareil annexe pour collecter ce type de données vous devrez renseigner le modèle de l’appareil, les protocoles qu’ils respectent (ex: ISO15197) et les données que vous comptez collecter avec auprès de Google.
Ci-dessous la liste des données considérées sensibles:
Datatype | Fields |
com.google.body.temperature.basal | body_temperature_measurement_location (int—enum)<br><br>body_temperature (float-celsius) |
com.google.blood_glucose | blood_glucose_level(float-mmol/L)<br><br>temporal_relation_to_meal(int-enum)<br><br>meal_type(int-enum)<br><br>temporal_relation_to_sleep(int-enum)<br><br>blood_glucose_specimen_source(int-enum) |
com.google.blood_pressure | blood_pressure_systolic(float-mmHg)<br><br>blood_pressure_diastolic(float-mmHg)<br><br>body_position(int-enum)<br><br>blood_pressure_measurement_location(int-enum) |
com.google.body.temperature | body_temperature(float-celsius)<br><br>body_temperature_measurement_location(int-enum) |
com.google.cervical_mucus | cervical_mucus_texture(int-enum)<br><br>cervical_mucus_amount(int-enum) |
com.google.cervical_position | cervical_position(int-enum)<br><br>cervical_dilation(int-enum)<br><br>cervical_firmness(int-enum) |
com.google.menstruation | menstrual_flow(int-enum) |
com.google.ovulation_test | ovulation_test_result(int-enum) |
com.google.oxygen_saturation | oxygen_saturation(float-percent)<br><br>supplemental_oxygen_flow_rate(float-L/min))<br><br>oxygen_therapy_administration_mode(int-enum)<br><br>oxygen_saturation_system(int-enum)<br><br>oxygen_saturation_measurement_method(int-enum) |
com.google.vaginal_spotting | field_occurrences(int-enum) |
Because health data is potentially sensitive, Google Fit restricts write access for the data types in HealthDataTypes to only certain developers.
TABLE 2: HealthDataType
Si malgré tout aucunes de ces données ne vous conviennent, Google vous donne la possibilité de créer la vôtre et de lui donner une visibilité public, private, shareable, restricted. C’est le cas de Nike et Adidas qui ont tous deux créé leur propre type de donnée.
2.3 Dataset & DataPoint
Un dataset quant à lui est toujours instancié à l’aide d’une datasource. Le dataset contient plusieurs datapoints qui représentent une donnée brute à un instant t. Prenons un exemple, afin d’éclaircir notre discours:
Camille décide de faire un jogging d’une heure le dimanche matin. Reprenant le sport depuis peu elle n’arrive pas à terminer son jogging entièrement. Elle a couru les 30 premières minutes puis a marché 10 minutes afin de se reposer et a repris la fin de sa course pendant les 20 minutes restantes.
Essayons maintenant de traduire cette activité physique avec les objets que nous avons décrits précédemment. Tout d’abord il faut choisir ce que l’on souhaite enregistrer dans le “Fitness Store”. En se référant au tableau 1 en 2.2, nous décidons d’enregistrer la vitesse de Camille ainsi que l’activité qu’elle a pratiqué. On construit un premier dataset instancié à partir d’une datasource de datatype ACTIVITY_SEGMENT
(toujours en se référant au tableau en 2.2 colonne 4).
Ensuite on insère trois datapoints correspondants aux trois phases du jogging de Camille (course puis marche puis course). Attention puisque l’on a choisi une datasource ACTIVITY_SEGMENT
, les champs des datapoints doivent correspondre à ceux du tableau 1 en 2.2 suivant le datatype que l’on a sélectionné. Ici ce sera le FIELD_ACTIVITY
comme l'indique la colonne 3.
De la même manière on peut crée un deuxième dataset à partir d’une datasource de datatype TYPE_SPEED
nous obligeant à insérer des trois datapoints avec les champs FIELD_SPEED
cette fois-ci.
La Figure 4 se propose de résumer cet exemple graphiquement:
FIGURE 4: Exemple d’une session de running
On remarque qu’en choisissant une datasource on établit en quelque sorte un contrat nous engageant à fournir des datapoints possédants les champs correspondants au datatype de la datasource (voir tableau en 2.2). On peut donc dire qu’un dataset regroupe plusieurs datapoints de même “type”. C’est pourquoi il existe des sessions qui elles vont regrouper plusieurs datasets qui pourront être de types différents.
Pour terminer l’insertion on utilise HistoryAPI:
3. Play with data
Dans l’exemple précédent nous avons insérer des données sportives mais le scénario est identique pour insérer des aliments ou des données liées à la santé (sommeil, taille, poids, …). Il faut retenir que le datatype décrit la structure des datapoints que vous devrez compléter.
Pour insérer une donnée il faut donc une datasource qui précise le package name car une application ne peut accéder qu’aux données qu’elle a elle même inséré dans le "Fitness Store" (cas particulier du nombre de pas avec RecordingApi et des objectifs avec GoalsApi). Noter que pour insérer un datapoint vous devez obligatoirement renseigner tous les champs du DataType que vous avez sélectionné.
3.2 Read Data
Pour lire les données du jogging de Camille on utilise la requête suivante:
Pour supprimer ou mettre à jour des données, le principe reste le même mais il vous faudra utiliser les objets DataDeleteRequest
et DataUpdateRequest
.
A Retenir:
- Tous les champs du datapoint doivent être remplis
- Utilisez
HistoryApi.updateData
si vous insérez deux datapoints qui se chevauchent sinon la requête d’insertion sera ignorée. - Vous ne pouvez pas modifier de données insérées par une autre application.
- Vous ne pouvez pas supprimer de données insérées par une autre application.
- Requêtes limitées à 1000 DataPoints
- Les données peuvent ensuite être englobés en sessions.
3.3 Insert Session
Comme nous l’évoquions précédemment il est possible de créer des sessions, il nous faut utiliser SessionApi.
Actuellement Google propose 124 activités sportives pour vos sessions.
FIGURE 5: Fitness activities available on Google Fit
Les sessions représentent un regroupement de dataset pour l’exemple de Camille la session serait de type RUNNING. Même si elle a marché, initialement cela reste une session de Jogging pour elle. Attention donc à ne pas confondre l’activité que l’on affecte à un datapoint et à une session.
Plus concrètement, vous avez deux manières d’insérer une session, soit directement via une insertion manuelle.
Soit en lançant un enregistrement.
En lançant un enregistrement Google Fit collecte lui même les datapoints et les insère dans le “Fitness Store”. Pratique !
3.4 Read Session
Une chose également appréciable avec les API Google Fit est que Google estime automatiquement les calories dépensées de l’utilisateur en fonction de l’activité physique pratiquée si vous ne les renseignez pas.
Conclusion
Google Fit fournit une plateforme complète qui permet de regrouper données sportives, données de santé et données alimentaires au même endroit afin d’offrir à l’utilisateur un environnement centralisé et cohérent afin qu’il bénéficie d’une meilleure expérience.
Cependant Google averti que l’utilisation de Google Fit doit être clair pour l’utilisateur donc toujours explicité, il avertit également que Google Fit ne doit pas être utilisé à des fins commerciales ou pour des données autres que celles citées précédemment. Enfin si les datatypes fournit par la plateforme ne vous conviennent pas il vous est toujours possible de créer la votre. Pour rappel c'est le cas de Nike et d'Adidas.
Au fil du temps Google Fit ne cesse de s'améliorer et permet maintenant de :
- Reconnaitre automatiquement le début d'une activité
- Notifier quand certaines données arrivent dans le "Fitness store" permettant ainsi de créer des expériences utilisateurs cohérentes (ie: Encourager l'utilisateur à faire une activité après un repas trop calorique, Encourager l'utilisateur à boire après un long entraînement, ...)
- Augmenter la fédération des utilisateurs envers votre application: J'entends ici qu'en tant que sportif je préfère toujours une application qui sera compatible Google Fit et qui pourra enrichir mon écosystème existant qu'une application isolée.
Ces APIs gagnent à être connues et leurs intégration au sein d'Android Wear ouvrent de belles perspectives.
Sources
https://developers.google.com/fit/android/
https://www.youtube.com/watch?v=tP8yKNXXGmQ
table, th, td { font-size: 70%; } .caption { color: #767676; font-size: 12px; font-style: italic; margin-bottom:25px; }