Présentation des capteurs

La plupart des appareils Android sont dotés de capteurs intégrés qui mesurent le mouvement, l'orientation et diverses conditions environnementales. Ces capteurs sont capables de fournir des données brutes avec une grande précision. Ils sont utiles si vous souhaitez surveiller les mouvements ou le positionnement tridimensionnels de l'appareil, ou si vous souhaitez surveiller les changements dans l'environnement ambiant à proximité d'un appareil. Par exemple, un jeu peut suivre les mesures du capteur de gravité d'un appareil pour déduire les gestes et les mouvements complexes de l'utilisateur, tels qu'une inclinaison, un tremblement, une rotation ou un swing. De même, une application météo peut utiliser le capteur de température et d'humidité d'un appareil pour calculer et signaler le point de rosée, ou une application de voyage peut utiliser le capteur de champ géomagnétique et l'accéléromètre pour signaler une direction de boussole.

La plate-forme Android est compatible avec trois grandes catégories de capteurs:

  • Capteurs de mouvement

    Ces capteurs mesurent les forces d'accélération et de rotation le long de trois axes. Cette catégorie inclut les accéléromètres, les capteurs de gravité, les gyroscopes et les capteurs de vecteurs de rotation.

  • Capteurs environnementaux

    Ces capteurs mesurent différents paramètres environnementaux, tels que la température et la pression de l'air ambiant, l'éclairage et l'humidité. Cette catégorie comprend les baromètres, les photomètres et les thermomètres.

  • Capteurs de position

    Ces capteurs mesurent la position physique d'un appareil. Cette catégorie inclut les capteurs d'orientation et les magnétomètres.

Vous pouvez accéder aux capteurs disponibles sur l'appareil et obtenir les données brutes des capteurs à l'aide du framework de capteurs Android. Le framework de capteurs fournit plusieurs classes et interfaces qui vous aident à effectuer une grande variété de tâches liées aux capteurs. Par exemple, vous pouvez utiliser le framework de capteurs pour effectuer les opérations suivantes:

  • Déterminer quels capteurs sont disponibles sur un appareil
  • Déterminez les caractéristiques d'un capteur : portée maximale, fabricant, alimentation requise et résolution.
  • Récupérer des données de capteur brutes et définir le taux minimal d'obtention de données de capteurs
  • Permet d'enregistrer et d'annuler l'enregistrement des écouteurs d'événements de capteurs qui surveillent les modifications des capteurs.

Cet article présente les capteurs disponibles sur la plate-forme Android. Il présente également la structure des capteurs.

Présentation des capteurs

Le framework de capteurs Android vous permet d'accéder à de nombreux types de capteurs. Certains de ces capteurs sont matériels et d'autres basés sur un logiciel. Les capteurs matériels sont des composants physiques intégrés à un téléphone ou une tablette. Elles extraient leurs données en mesurant directement des propriétés environnementales spécifiques, telles que l'accélération, l'intensité du champ géomagnétique ou le changement angulaire. Les capteurs logiciels ne sont pas des appareils physiques, bien qu'ils imitent des capteurs matériels. Les capteurs basés sur des logiciels tirent leurs données d'un ou de plusieurs capteurs matériels et sont parfois appelés capteurs virtuels ou capteurs synthétiques. Le capteur d'accélération linéaire et le capteur de gravité sont des exemples de capteurs logiciels. Le tableau 1 récapitule les capteurs compatibles avec la plate-forme Android.

Peu d'appareils Android sont équipés de tous les types de capteurs. Par exemple, la plupart des téléphones et des tablettes sont équipés d'un accéléromètre et d'un magnétomètre, mais moins d'appareils sont équipés de baromètres ou de thermomètres. En outre, un appareil peut être doté de plusieurs capteurs d'un type donné. Par exemple, un appareil peut disposer de deux capteurs de gravité, chacun ayant une portée différente.

Tableau 1. Types de capteurs compatibles avec la plate-forme Android.

Capteur Type Description Utilisations courantes
TYPE_ACCELEROMETER Matériel Mesure la force d'accélération en m/s2 appliquée à un appareil sur les trois axes physiques (x, y et z), y compris la force de gravité. Détection des mouvements (secousses, inclinaison, etc.)
TYPE_AMBIENT_TEMPERATURE Matériel Mesure la température ambiante de la pièce en degrés Celsius (°C). Voir la remarque ci-dessous. Surveillance de la température de l'air.
TYPE_GRAVITY Logiciels ou matériels Mesure la force de gravité en m/s2, appliquée à un appareil sur les trois axes physiques (x, y, z). Détection des mouvements (secousses, inclinaison, etc.)
TYPE_GYROSCOPE Matériel Mesure la vitesse de rotation d'un appareil en rad/s autour de chacun des trois axes physiques (x, y et z). Détection de rotation (rotation, rotation, etc.).
TYPE_LIGHT Matériel Mesure le niveau de luminosité ambiante (éclairage) en lx. Contrôler la luminosité de l'écran.
TYPE_LINEAR_ACCELERATION Logiciels ou matériels Mesure la force d'accélération en m/s2 appliquée à un appareil sur les trois axes physiques (x, y et z), à l'exclusion de la force de gravité. Surveillez l'accélération sur un seul axe.
TYPE_MAGNETIC_FIELD Matériel Mesure le champ géomagnétique ambiant pour les trois axes physiques (x, y, z) en μT. Création d'une boussole.
TYPE_ORIENTATION Logiciels Mesure les degrés de rotation d'un appareil autour des trois axes physiques (x, y, z). À partir du niveau d'API 3, vous pouvez obtenir la matrice d'inclinaison et la matrice de rotation d'un appareil en utilisant le capteur de gravité et le capteur de champ géomagnétique conjointement avec la méthode getRotationMatrix(). Détermination de la position de l'appareil...
TYPE_PRESSURE Matériel Mesure la pression de l'air ambiant en hPa ou mbar. Surveillance des variations de pression atmosphérique.
TYPE_PROXIMITY Matériel Mesure la proximité d'un objet en cm par rapport à l'écran d'affichage d'un appareil. Ce capteur est généralement utilisé pour déterminer si un téléphone est tenu contre l'oreille d'une personne. Position du téléphone pendant un appel.
TYPE_RELATIVE_HUMIDITY Matériel Mesure l'humidité ambiante relative en pourcentage (%). Surveillance du point de rosée, de l'humidité absolue et relative.
TYPE_ROTATION_VECTOR Logiciels ou matériels Mesure l'orientation d'un appareil en fournissant les trois éléments du vecteur de rotation de l'appareil. Détection des mouvements et des rotations
TYPE_TEMPERATURE Matériel Mesure la température de l'appareil en degrés Celsius (°C). L'implémentation de ce capteur varie selon les appareils. Ce capteur a été remplacé par le capteur TYPE_AMBIENT_TEMPERATURE au niveau d'API 14. Surveillance des températures.

Structure de capteurs

Vous pouvez accéder à ces capteurs et récupérer les données brutes des capteurs à l'aide du framework de capteurs Android. Le framework de capteur fait partie du package android.hardware et inclut les classes et les interfaces suivantes:

SensorManager
Vous pouvez utiliser cette classe pour créer une instance du service de capteurs. Cette classe fournit plusieurs méthodes pour accéder aux capteurs et les répertorier, enregistrer et annuler l'enregistrement des écouteurs d'événements de capteurs, et obtenir des informations d'orientation. Cette classe fournit également plusieurs constantes de capteur qui permettent de signaler la précision des capteurs, de définir les taux d'acquisition de données et de calibrer les capteurs.
Sensor
Vous pouvez utiliser cette classe pour créer une instance d'un capteur spécifique. Cette classe fournit différentes méthodes qui vous permettent de déterminer les capacités d'un capteur.
SensorEvent
Le système utilise cette classe pour créer un objet d'événement de capteur, qui fournit des informations sur un événement de capteur. Un objet d'événement de capteur inclut les informations suivantes: les données brutes des capteurs, le type de capteur ayant généré l'événement, la précision des données et l'horodatage de l'événement.
SensorEventListener
Vous pouvez utiliser cette interface pour créer deux méthodes de rappel qui reçoivent des notifications (événements de capteurs) lorsque les valeurs des capteurs changent ou que la précision du capteur change.

Dans une application classique, les API liées aux capteurs permettent d'effectuer deux tâches de base:

  • Identifier les capteurs et leurs fonctionnalités

    L'identification des capteurs et de leurs caractéristiques au moment de l'exécution est utile si votre application possède des fonctionnalités qui dépendent de types ou de fonctionnalités de capteurs spécifiques. Par exemple, vous pouvez identifier tous les capteurs installés sur un appareil et désactiver toutes les fonctionnalités d'application qui reposent sur des capteurs absents. De même, il peut être utile d'identifier tous les capteurs d'un type donné afin de choisir l'implémentation qui offre les meilleures performances à votre application.

  • Surveiller les événements de capteurs

    La surveillance des événements de capteurs vous permet d'obtenir les données brutes des capteurs. Un événement de capteur se produit chaque fois qu'un capteur détecte une modification des paramètres qu'il mesure. Un événement de capteur fournit quatre informations: le nom du capteur ayant déclenché l'événement, l'horodatage de l'événement, la précision de l'événement et les données brutes des capteurs qui ont déclenché l'événement.

Disponibilité des capteurs

Bien que la disponibilité des capteurs varie d'un appareil à l'autre, elle peut également varier d'une version d'Android à l'autre. En effet, les capteurs Android ont été introduits au cours de plusieurs versions de la plate-forme. Par exemple, de nombreux capteurs ont été introduits dans Android 1.5 (niveau d'API 3), mais certains n'ont pas été implémentés et ne peuvent être utilisés qu'avec Android 2.3 (niveau d'API 9). De même, plusieurs capteurs ont été introduits dans Android 2.3 (niveau d'API 9) et Android 4.0 (niveau d'API 14). Deux capteurs ont été abandonnés et remplacés par de nouveaux capteurs plus performants.

Le tableau 2 récapitule la disponibilité de chaque capteur en fonction de la plate-forme. Seules quatre plates-formes sont listées, car il s'agit de celles qui ont impliqué des changements de capteurs. Les capteurs répertoriés comme obsolètes restent disponibles sur les plates-formes suivantes (à condition qu'ils soient présents sur un appareil), ce qui est conforme aux règles de compatibilité ascendante d'Android.

Tableau 2. Disponibilité des capteurs par plate-forme.

Capteur Android 4.0
(niveau d'API 14)
Android 2.3
(niveau d'API 9)
Android 2.2
(niveau d'API 8)
Android 1.5
(niveau d'API 3)
TYPE_ACCELEROMETER Oui. Oui Oui Oui
TYPE_AMBIENT_TEMPERATURE Oui. N/A n/a N/A
TYPE_GRAVITY Oui. Oui. N/A N/A
TYPE_GYROSCOPE Oui. Oui. N/A1 N/A1
TYPE_LIGHT Oui. Oui Oui Oui
TYPE_LINEAR_ACCELERATION Oui Oui. N/A N/A
TYPE_MAGNETIC_FIELD Oui. Oui Oui Oui.
TYPE_ORIENTATION Oui2 Oui2 Oui2 Oui.
TYPE_PRESSURE Oui Oui. N/A1 N/A1
TYPE_PROXIMITY Oui. Oui Oui Oui
TYPE_RELATIVE_HUMIDITY Oui. N/A n/a N/A
TYPE_ROTATION_VECTOR Oui. Oui. N/A N/A
TYPE_TEMPERATURE Oui2 Oui. Oui Oui.

1 Ce type de capteur a été ajouté dans Android 1.5 (niveau d'API 3), mais il n'était disponible qu'avec Android 2.3 (niveau d'API 9).

2 Ce capteur est disponible, mais il est obsolète.

Identifier les capteurs et leurs capacités

Le framework de capteurs Android propose plusieurs méthodes pour vous permettre de déterminer facilement au moment de l'exécution quels capteurs se trouvent sur un appareil. L'API fournit également des méthodes qui vous permettent de déterminer les capacités de chaque capteur, telles que sa portée maximale, sa résolution et ses besoins en puissance.

Pour identifier les capteurs installés sur un appareil, vous devez d'abord obtenir une référence au service de capteurs. Pour ce faire, vous créez une instance de la classe SensorManager en appelant la méthode getSystemService() et en transmettant l'argument SENSOR_SERVICE. Par exemple :

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

Vous pouvez ensuite obtenir la liste de tous les capteurs d'un appareil en appelant la méthode getSensorList() et en utilisant la constante TYPE_ALL. Par exemple :

Kotlin

val deviceSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)

Java

List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);

Si vous souhaitez répertorier tous les capteurs d'un type donné, vous pouvez utiliser une autre constante à la place de TYPE_ALL, telle que TYPE_GYROSCOPE, TYPE_LINEAR_ACCELERATION ou TYPE_GRAVITY.

Vous pouvez également déterminer si un type de capteur spécifique existe sur un appareil en utilisant la méthode getDefaultSensor() et en transmettant la constante de type pour un capteur spécifique. Si un appareil est équipé de plusieurs capteurs d'un type donné, l'un des capteurs doit être désigné comme capteur par défaut. S'il n'existe pas de capteur par défaut pour un type de capteur donné, l'appel de méthode renvoie la valeur "null", ce qui signifie que l'appareil ne possède pas ce type de capteur. Par exemple, le code suivant permet de vérifier si l'appareil est équipé d'un magnétomètre:

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

Remarque:Android n'impose pas aux fabricants d'appareils d'intégrer des types particuliers de capteurs à leurs appareils Android. Ces appareils peuvent donc avoir un large éventail de configurations de capteurs.

En plus de répertorier les capteurs installés sur un appareil, vous pouvez utiliser les méthodes publiques de la classe Sensor pour déterminer les caractéristiques et les attributs de chaque capteur. Cela est utile si vous souhaitez que votre application se comporte différemment en fonction des capteurs ou des fonctionnalités de capteurs disponibles sur un appareil. Par exemple, vous pouvez utiliser les méthodes getResolution() et getMaximumRange() pour obtenir la résolution et la plage de mesure maximale d'un capteur. Vous pouvez également utiliser la méthode getPower() pour obtenir les exigences d'alimentation d'un capteur.

Deux des méthodes publiques sont particulièrement utiles si vous souhaitez optimiser votre application pour différents capteurs de fabricant ou différentes versions d'un capteur. Par exemple, si votre application doit surveiller les gestes des utilisateurs tels que l'inclinaison et le tremblement, vous pouvez créer un ensemble de règles et d'optimisations de filtrage des données pour les appareils plus récents dotés du capteur de gravité d'un fournisseur spécifique, et un autre ensemble de règles et d'optimisations de filtrage des données pour les appareils qui ne sont pas équipés d'un capteur de gravité et ne disposent que d'un accéléromètre. L'exemple de code suivant vous montre comment utiliser les méthodes getVendor() et getVersion() pour ce faire. Dans cet exemple, nous recherchons un capteur de gravité qui indique Google LLC comme fournisseur et dont le numéro de version est 3. Si ce capteur n'est pas présent sur l'appareil, nous essayons d'utiliser l'accéléromètre.

Kotlin

private lateinit var sensorManager: SensorManager
private var mSensor: Sensor? = null

...

sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) {
    val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY)
    // Use the version 3 gravity sensor.
    mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 }
}
if (mSensor == null) {
    // Use the accelerometer.
    mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    } else {
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
        null
    }
}

Java

private SensorManager sensorManager;
private Sensor mSensor;

...

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = null;

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
    List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
    for(int i=0; i<gravSensors.size(); i++) {
        if ((gravSensors.get(i).getVendor().contains("Google LLC")) &&
           (gravSensors.get(i).getVersion() == 3)){
            // Use the version 3 gravity sensor.
            mSensor = gravSensors.get(i);
        }
    }
}
if (mSensor == null){
    // Use the accelerometer.
    if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
        mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    } else{
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
    }
}

La méthode getMinDelay() est une autre méthode utile, qui renvoie l'intervalle de temps minimal (en microsecondes) qu'un capteur peut utiliser pour détecter des données. Tout capteur qui renvoie une valeur non nulle pour la méthode getMinDelay() est un capteur de flux continu. Les capteurs de flux détectent les données à intervalles réguliers et ont été introduits dans Android 2.3 (niveau d'API 9). Si un capteur renvoie zéro lorsque vous appelez la méthode getMinDelay(), cela signifie qu'il ne s'agit pas d'un capteur de flux, car il ne transmet des données que lorsqu'il y a un changement dans les paramètres qu'il détecte.

La méthode getMinDelay() est utile, car elle vous permet de déterminer le débit maximal auquel un capteur peut acquérir des données. Si certaines fonctionnalités de votre application nécessitent des taux d'acquisition de données élevés ou un capteur de flux, vous pouvez utiliser cette méthode pour déterminer si un capteur répond à ces exigences, puis activer ou désactiver les fonctionnalités pertinentes dans votre application en conséquence.

Attention:Le taux d'acquisition de données maximal d'un capteur n'est pas nécessairement le taux auquel le framework de capteur fournit les données des capteurs à votre application. Le framework de capteur transmet les données via les événements de capteurs. Plusieurs facteurs influencent la fréquence à laquelle votre application reçoit des événements de capteur. Pour en savoir plus, consultez la page Surveiller les événements des capteurs.

Surveiller les événements des capteurs

Pour surveiller les données brutes des capteurs, vous devez implémenter deux méthodes de rappel exposées via l'interface SensorEventListener: onAccuracyChanged() et onSensorChanged(). Le système Android appelle ces méthodes dans les cas suivants:

  • La précision d'un capteur change.

    Dans ce cas, le système appelle la méthode onAccuracyChanged() et vous fournit une référence à l'objet Sensor qui a été modifié et à la nouvelle précision du capteur. La précision est représentée par l'une des quatre constantes d'état : SENSOR_STATUS_ACCURACY_LOW, SENSOR_STATUS_ACCURACY_MEDIUM, SENSOR_STATUS_ACCURACY_HIGH ou SENSOR_STATUS_UNRELIABLE.

  • Un capteur signale une nouvelle valeur.

    Dans ce cas, le système appelle la méthode onSensorChanged(), ce qui vous fournit un objet SensorEvent. Un objet SensorEvent contient des informations sur les nouvelles données de capteur, y compris l'exactitude des données, le capteur ayant généré les données, le code temporel correspondant au moment où les données ont été générées et les nouvelles données enregistrées par le capteur.

Le code suivant montre comment utiliser la méthode onSensorChanged() pour surveiller les données du capteur de lumière. Cet exemple affiche les données brutes du capteur dans un TextView défini dans le fichier main.xml en tant que sensor_data.

Kotlin

class SensorActivity : Activity(), SensorEventListener {
    private lateinit var sensorManager: SensorManager
    private var mLight: Sensor? = null

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
    }

    override fun onSensorChanged(event: SensorEvent) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        val lux = event.values[0]
        // Do something with this sensor value.
    }

    override fun onResume() {
        super.onResume()
        mLight?.also { light ->
            sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onPause() {
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

Java

public class SensorActivity extends Activity implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor mLight;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        float lux = event.values[0];
        // Do something with this sensor value.
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

Dans cet exemple, le délai de données par défaut (SENSOR_DELAY_NORMAL) est spécifié lorsque la méthode registerListener() est appelée. Le délai (ou taux d'échantillonnage) des données contrôle l'intervalle auquel les événements de capteurs sont envoyés à votre application via la méthode de rappel onSensorChanged(). Le délai de données par défaut convient à la surveillance des changements d'orientation d'écran typiques et utilise un délai de 200 000 microsecondes. Vous pouvez spécifier d'autres délais de données, tels que SENSOR_DELAY_GAME (délai de 20 000 microsecondes), SENSOR_DELAY_UI (délai de 60 000 microsecondes) ou SENSOR_DELAY_FASTEST (délai de 0 microseconde). À partir d'Android 3.0 (niveau d'API 11), vous pouvez également spécifier le délai en tant que valeur absolue (en microsecondes).

Le délai que vous spécifiez n'est qu'un délai suggéré. Le système Android et d'autres applications peuvent modifier ce délai. Il est recommandé de spécifier le délai maximal possible, car le système utilise généralement un délai inférieur à celui que vous spécifiez (vous devez donc choisir le taux d'échantillonnage le plus lent qui répond toujours aux besoins de votre application). L'utilisation d'un délai plus élevé entraîne une charge plus faible sur le processeur et consomme donc moins d'énergie.

Il n'existe aucune méthode publique pour déterminer le taux auquel le framework de capteurs envoie des événements de capteur à votre application. Toutefois, vous pouvez utiliser les codes temporels associés à chaque événement de capteur pour calculer le taux d'échantillonnage sur plusieurs événements. Vous ne devriez pas avoir à modifier le taux d'échantillonnage (retard) une fois que vous l'avez défini. Si vous devez modifier le délai, vous devez annuler l'enregistrement, puis réenregistrer l'écouteur du capteur.

Il est également important de noter que cet exemple utilise les méthodes de rappel onResume() et onPause() pour enregistrer et annuler l'enregistrement de l'écouteur d'événements de capteur. Nous vous recommandons de toujours désactiver les capteurs dont vous n'avez pas besoin, en particulier lorsque votre activité est suspendue. À défaut, la batterie risque de se décharger en quelques heures, car certains capteurs ont une consommation importante et peuvent rapidement utiliser la batterie. Le système ne désactive pas automatiquement les capteurs lorsque l'écran s'éteint.

Gérer les différentes configurations de capteurs

Android ne spécifie pas de configuration de capteur standard pour les appareils. Les fabricants d'appareils peuvent donc intégrer n'importe quelle configuration de capteur à leurs appareils Android. Par conséquent, les appareils peuvent inclure divers capteurs dans de nombreuses configurations. Si votre application repose sur un type de capteur spécifique, vous devez vous assurer qu'il est présent sur un appareil pour que votre application puisse s'exécuter correctement.

Vous avez deux options pour vous assurer qu'un capteur donné est présent sur un appareil:

  • Détecter les capteurs au moment de l'exécution et activer ou désactiver les fonctionnalités de l'application, le cas échéant
  • Utilisez les filtres Google Play pour cibler les appareils avec des configurations de capteurs spécifiques.

Chaque option est abordée dans les sections suivantes.

Détecter les capteurs au moment de l'exécution

Si votre application utilise un type de capteur spécifique, mais qui ne s'appuie pas dessus, vous pouvez utiliser le framework de capteurs pour détecter le capteur au moment de l'exécution, puis activer ou désactiver les fonctionnalités de l'application, le cas échéant. Par exemple, une application de navigation peut utiliser les capteurs de température, de pression, GPS et de champ géomagnétique pour afficher la température, la pression barométrique, la position et le relèvement de la boussole. Si un appareil n'est pas doté d'un capteur de pression, vous pouvez utiliser le framework de capteurs pour détecter son absence au moment de l'exécution, puis désactiver la partie de l'interface utilisateur de votre application qui affiche la pression. Par exemple, le code suivant vérifie si un capteur de pression est installé sur un appareil:

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) {
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

Utiliser les filtres Google Play pour cibler des configurations de capteurs spécifiques

Si vous publiez votre application sur Google Play, vous pouvez utiliser l'élément <uses-feature> dans votre fichier manifeste pour la filtrer dans les appareils qui ne disposent pas de la configuration de capteur appropriée pour votre application. L'élément <uses-feature> comporte plusieurs descripteurs matériels qui vous permettent de filtrer les applications en fonction de la présence de capteurs spécifiques. Vous pouvez lister les capteurs suivants : accéléromètre, baromètre, boussole (champ géomagnétique), gyroscope, lumière et proximité. Voici un exemple d'entrée de fichier manifeste qui filtre les applications sans accéléromètre:

<uses-feature android:name="android.hardware.sensor.accelerometer"
              android:required="true" />

Si vous ajoutez cet élément et ce descripteur au fichier manifeste de votre application, les utilisateurs ne verront votre application sur Google Play que si leur appareil est équipé d'un accéléromètre.

Vous ne devez définir le descripteur sur android:required="true" que si votre application repose entièrement sur un capteur spécifique. Si votre application utilise un capteur pour une fonctionnalité, mais qu'elle continue de s'exécuter sans le capteur, vous devez le répertorier dans l'élément <uses-feature>, mais définir le descripteur sur android:required="false". Cela permet de garantir que les appareils peuvent installer votre application même s'ils ne disposent pas de ce capteur. Il s'agit également d'une bonne pratique de gestion de projet qui vous aide à suivre les fonctionnalités utilisées par votre application. N'oubliez pas que si votre application utilise un capteur particulier, mais qu'elle fonctionne toujours sans le capteur, vous devez le détecter au moment de l'exécution, puis désactiver ou activer les fonctionnalités de l'application, le cas échéant.

Système de coordonnées du capteur

En général, le framework de capteur utilise un système de coordonnées à trois axes standard pour exprimer les valeurs des données. Pour la plupart des capteurs, le système de coordonnées est défini par rapport à l'écran de l'appareil lorsque celui-ci est tenu dans son orientation par défaut (voir la figure 1). Lorsqu'un appareil est maintenu dans son orientation par défaut, l'axe X est horizontal et pointe vers la droite, l'axe Y est vertical et pointe vers le haut, et l'axe Z pointe vers l'extérieur de la face de l'écran. Dans ce système, les coordonnées derrière l'écran ont des valeurs Z négatives. Ce système de coordonnées est utilisé par les capteurs suivants:

Figure 1 : Système de coordonnées (relatif à un appareil) utilisé par l'API Sensor.

Le point le plus important à comprendre sur ce système de coordonnées est que les axes ne sont pas échangés lorsque l'orientation de l'écran de l'appareil change. En d'autres termes, le système de coordonnées du capteur ne change jamais lorsque l'appareil bouge. Ce comportement est identique à celui du système de coordonnées OpenGL.

Il est également important de comprendre que votre application ne doit pas supposer que l'orientation naturelle (par défaut) d'un appareil est en mode portrait. Sur de nombreuses tablettes, l'orientation naturelle est le mode paysage. De plus, le système de coordonnées du capteur est toujours basé sur l'orientation naturelle de l'appareil.

Enfin, si votre application fait correspondre les données des capteurs à l'affichage à l'écran, vous devez utiliser la méthode getRotation() pour déterminer la rotation de l'écran, puis la méthode remapCoordinateSystem() pour mapper les coordonnées du capteur aux coordonnées de l'écran. Vous devez effectuer cette opération même si votre fichier manifeste spécifie un affichage en mode portrait uniquement.

Remarque:Certains capteurs et méthodes utilisent un système de coordonnées relatif au cadre de référence mondial (par opposition au cadre de référence de l'appareil). Ces capteurs et méthodes renvoient des données qui représentent le mouvement ou la position de l'appareil par rapport à la Terre. Pour en savoir plus, consultez les méthodes getOrientation() et getRotationMatrix(), ainsi que les sections Capteur d'orientation et Capteur de vecteur de rotation.

Limitation du débit des capteurs

Pour protéger les informations potentiellement sensibles sur les utilisateurs, si votre application cible Android 12 (niveau d'API 31) ou une version ultérieure, le système limite la fréquence d'actualisation des données de certains capteurs de mouvement et de position. Ces données incluent les valeurs enregistrées par l'accéléromètre, le gyroscope et le capteur de champ géomagnétique de l'appareil.

La fréquence d'actualisation maximale dépend de la manière dont vous accédez aux données des capteurs:

Si votre application doit collecter les données des capteurs de mouvement à un taux plus élevé, vous devez déclarer l'autorisation HIGH_SAMPLING_RATE_SENSORS, comme indiqué dans l'extrait de code suivant. Sinon, si votre application tente de collecter des données de capteurs de mouvement à une fréquence plus élevée sans déclarer cette autorisation, une SecurityException se produit.

AndroidManifest.xml

<manifest ...>
    <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>
    <application ...>
        ...
    </application>
</manifest>

Bonnes pratiques d'accès aux capteurs et de leur utilisation

Lorsque vous concevez la mise en œuvre de vos capteurs, veillez à suivre les instructions décrites dans cette section. Ces consignes sont les bonnes pratiques recommandées à toute personne qui utilise le framework de capteurs pour accéder aux capteurs et acquérir des données de capteurs.

Ne collecter les données des capteurs qu'au premier plan

Sur les appareils équipés d'Android 9 (niveau d'API 28) ou version ultérieure, les applications exécutées en arrière-plan sont soumises aux restrictions suivantes:

  • Les capteurs qui utilisent le mode de création de rapports continu, tels que les accéléromètres et les gyroscopes, ne reçoivent pas d'événements.
  • Les capteurs qui utilisent le mode de création de rapports on-change ou one-shot ne reçoivent pas d'événements.

Compte tenu de ces restrictions, il est préférable de détecter les événements de capteurs lorsque votre application est exécutée au premier plan ou dans un service de premier plan.

Annuler l'enregistrement des écouteurs de capteurs

Veillez à annuler l'enregistrement de l'écouteur d'un capteur lorsque vous avez fini de l'utiliser ou lorsque l'activité du capteur est mise en pause. Si un écouteur de capteur est enregistré et que son activité est suspendue, le capteur continue d'acquérir des données et d'utiliser les ressources de la batterie, sauf si vous annulez l'enregistrement du capteur. Le code suivant montre comment utiliser la méthode onPause() pour annuler l'enregistrement d'un écouteur:

Kotlin

private lateinit var sensorManager: SensorManager
...
override fun onPause() {
    super.onPause()
    sensorManager.unregisterListener(this)
}

Java

private SensorManager sensorManager;
...
@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

Pour en savoir plus, consultez unregisterListener(SensorEventListener).

Tester avec Android Emulator

Android Emulator comprend un ensemble de commandes de capteurs virtuels qui vous permettent de tester des capteurs tels que l'accéléromètre, la température ambiante, le magnétomètre, la proximité, la luminosité, etc.

L'émulateur utilise une connexion avec un appareil Android qui exécute l'application SdkControllerSensor. Notez que cette application n'est disponible que sur les appareils équipés d'Android 4.0 (niveau d'API 14) ou version ultérieure. (Si l'appareil est équipé d'Android 4.0, la révision 2 doit être installée.) L'application SdkControllerSensor surveille les modifications apportées aux capteurs de l'appareil et les transmet à l'émulateur. L'émulateur est ensuite transformé en fonction des nouvelles valeurs qu'il reçoit des capteurs de votre appareil.

Vous pouvez afficher le code source de l'application SdkControllerSensor à l'emplacement suivant:

$ your-android-sdk-directory/tools/apps/SdkController

Pour transférer des données entre votre appareil et l'émulateur, procédez comme suit:

  1. Vérifiez que le débogage USB est activé sur votre appareil.
  2. Connectez votre appareil à votre ordinateur de développement à l'aide d'un câble USB.
  3. Lancez l'application SdkControllerSensor sur votre appareil.
  4. Dans l'application, sélectionnez les capteurs que vous souhaitez émuler.
  5. Exécutez la commande adb suivante:

  6. $ adb forward tcp:1968 tcp:1968
    
  7. Démarrez l'émulateur. Vous devriez maintenant pouvoir appliquer des transformations à l'émulateur en déplaçant votre appareil.

Remarque : Si les mouvements que vous effectuez sur votre appareil physique ne transforment pas l'émulateur, essayez d'exécuter à nouveau la commande adb de l'étape 5.

Pour en savoir plus, consultez le guide de l'émulateur Android.

Ne pas bloquer la méthode onSensorChanged()

Les données des capteurs peuvent changer à un taux élevé, ce qui signifie que le système peut appeler la méthode onSensorChanged(SensorEvent) assez souvent. Nous vous recommandons d'effectuer le moins d'opérations possible dans la méthode onSensorChanged(SensorEvent) afin de ne pas la bloquer. Si votre application nécessite un filtrage ou une réduction des données de capteurs, vous devez effectuer cette tâche en dehors de la méthode onSensorChanged(SensorEvent).

Évitez d'utiliser des méthodes ou des types de capteurs obsolètes

Plusieurs méthodes et constantes ont été abandonnées. Plus spécifiquement, le type de capteur TYPE_ORIENTATION a été abandonné. Pour obtenir les données d'orientation, utilisez plutôt la méthode getOrientation(). De même, le type de capteur TYPE_TEMPERATURE a été abandonné. Vous devez utiliser le type de capteur TYPE_AMBIENT_TEMPERATURE à la place sur les appareils équipés d'Android 4.0.

Vérifiez les capteurs avant de les utiliser

Vérifiez toujours qu'un capteur se trouve sur un appareil avant d'essayer d'obtenir des données à partir de celui-ci. Ne partez pas du principe qu'un capteur existe simplement parce qu'il s'agit d'un capteur fréquemment utilisé. Les fabricants ne sont pas tenus de fournir des capteurs particuliers dans leurs appareils.

Choisissez soigneusement les retards des capteurs

Lorsque vous enregistrez un capteur avec la méthode registerListener(), veillez à choisir une fréquence de diffusion adaptée à votre application ou à votre cas d'utilisation. Les capteurs peuvent fournir des données à des débits très élevés. Permettre au système d'envoyer des données supplémentaires dont vous n'avez pas besoin consomme des ressources système et consomme de la batterie.