Android Things: Comprendre et rédiger des pilotes
French (Français) translation by New Lune (you can also view the original English article)
Dans l'article précédent de cette série, vous avez appris les différents types de périphériques d'entrée et de sortie et les connexions qui peuvent être utilisés avec Android Things. Ensuite, vous pouvez développer cette connaissance pour écrire de nouvelles classes, connues sous le nom de pilotes, qui facilitent l'interface avec les périphériques. Cet article se concentrera sur le type de pilotes qui peuvent être écrits pour Android Things.
Astuces Android pour les pilotes d'espace utilisateur
Les pilotes d'espace utilisateur permettent aux développeurs d'injecter du nouveau matériel dans le cadre Android, ce qui leur permet d'interagir avec les API Android déjà établies. Bien que vous puissiez communiquer directement avec des périphériques utilisant les API d'entrée/sortie standard, l'écriture d'un pilote personnalisé permettra à votre application de prendre en charge divers profils matériels et de travailler directement avec le système d'exploitation Android. En outre, votre code sera plus structuré et facilitera facilement la réutilisation du code.
Il existe trois classifications de pilotes principales que vous allez apprendre dans cet article: Pilotes GPS, les pilotes de périphérique d'entrée humaine (HID) et les pilotes de capteur.
Pilotes GPS
Si votre appareil a besoin d'informations de localisation, vous pouvez ajouter un périphérique GPS à votre application. En enregistrant votre périphérique GPS avec UserDriverManager
, vous pourrez injecter les données de localisation de votre appareil dans la structure Android, ce qui permet d'utiliser les services de localisation d'Android. Cela combinera les données GPS avec Wi-Fi et n'importe quelle autre source de localisation pour fournir des résultats de données plus précis pour votre application.
Généralement, vos modules GPS se connecteront à un appareil Android Things via une connexion UART. Nous n'irons pas trop en profondeur sur UART dans ce tutoriel, mais vous pouvez apprendre tout sur la façon dont il fonctionne pour les périphériques dans le tutoriel précédent de cette série.



Pour travailler avec votre module GPS, vous devez créer un nouveau composant Java pour communiquer avec votre nouvel appareil. Nous appellerons cette classe GpsDriverService
.
Afin d'enregistrer votre module GPS avec la structure Android pour les données de localisation, vous devez d'abord créer un objet GpsDriver
dans votre GpsDriverService
. Cet objet peut être enregistré avec UserDriverManager
avec l'appel registerGpsDriver()
.
private GpsDriver mDriver; @Override public void onCreate() { super.onCreate(); mDriver = new GpsDriver(); UserDriverManager manager = UserDriverManager.getManager(); manager.registerGpsDriver( mDriver ); }
Une fois que votre module GPS a reçu des données de localisation et l'a envoyé à votre appareil Android Things via votre connexion UART série, vous devez l'analyser et l'ajouter à un objet Location
.
La plupart des modules GPS renvoient des données de localisation au format NMEA, bien que l'analyse de ces données dépasse le cadre de ce tutoriel. Il y a quatre éléments de données requis pour votre objet Location: précision, heure, latitude et longitude. Vous pouvez également inclure l'altitude, le roulement et la vitesse (si l'appareil est en mouvement).
private Location parseLocationFromString(String gpsData) { Location result = new Location(LocationManager.GPS_PROVIDER); //parse gpsData //required result.setAccuracy( getAccuracyFromGpsData( gpsData ) ); result.setTime( getTimeFromGpsData( gpsData ) ); result.setLatitude( getLatitudeFromGpsData( gpsData ) ); result.setLongitude( getLongitudeFromGpsData( gpsData ) ); //optional result.setAltitude( getAltitudeFromGpsData( gpsData ) ); result.setBearing( getBearingFromGpsData( gpsData ) ); result.setSpeed( getSpeedFromGpsData( gpsData ) ); return result; }
Une fois que votre objet Location
est rempli, vous pouvez le transmettre au GpsDriver
en appelant reportLocation()
.
Location location = parseLocationFromString( rawGpsData ); mDriver.reportLocation( location );
Une fois votre composant créé, vous devrez l'instancier, commencer à lire les données et écouter les mises à jour de votre application.
private LocationListener mLocationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { Log.v("Test", "Location update: " + location); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { Log.e("Test", "onstatuschanged"); } @Override public void onProviderEnabled(String provider) { Log.e("Test", "onproviderenabled"); } @Override public void onProviderDisabled(String provider) { Log.e("Test", "onproviderdisabled"); } }; ... mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // Create and start the GPS component mGpsDriver = new GpsDriverService(); mGpsDriver.register(); // Register for location updates mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
Lorsque votre application est terminée, vous devrez annuler l'enregistrement de votre pilote et supprimer votre écouteur d'emplacement.
@Override protected void onDestroy() { super.onDestroy(); if (mGpsDriver != null) { mGpsDriver.unregister(); mLocationManager.removeUpdates(mLocationListener); try { mGpsDriver.close(); } catch (IOException e) { } } }
En outre, vous devez vous assurer que votre application dispose de l'autorisation ACCESS_FINE_LOCATION
. Vous pouvez trouver des détails pour vous assurer qu'une application a des autorisations requises dans ce tutoriel.
Lors de la première utilisation d'une application utilisant une nouvelle permission dans Android Things, vous devrez redémarrer votre appareil après avoir installé votre application pour vous assurer que l'autorisation a été accordée.
Pilotes de périphériques d'entrée humains
Le cadre Android est livré avec un pipeline intégré pour gérer les entrées des boutons utilisateur et des événements de mouvement, ce qui est utilisé pour des fonctions telles que les boutons multimédia, les manettes de commande du contrôleur et les touches de clavier. En créant un InputDriver
, vous pouvez lier vos propres interactions humaines au pipeline d'entrée standard Android afin que votre appareil puisse réagir correctement à vos utilisateurs.
Pour simplifier, nous allons seulement regarder les événements d'entrée bouton et comment les lier dans le cadre Android, bien que les événements de mouvement sont traités d'une manière très similaire. Comme pour la dernière partie de ce tutoriel, nous ignorerons les détails d'implémentation plus spécifiques des périphériques d'entrée et nous nous concentrerons sur l'association des événements reçus à la plate-forme Android.
Événements de Bouton
Lorsqu'un événement de bouton se produit à partir d'un bouton que vous avez connecté à votre appareil Android Things, vous devez l'enregistrer et l'envoyer via le pipeline Android.
La première chose que vous devrez faire est de créer un objet InputDriver
dans un nouveau Service
et de l'initialiser. Le pilote peut être initialisé à l'aide d'un générateur qui accepte le type d'entrée, le nom de votre entrée, une version et un code de clé que le bouton représente.
private InputDriver mDriver; @Override public void onCreate() { super.onCreate(); mDriver = InputDriver.builder(InputDevice.SOURCE_CLASS_BUTTON) .setName("ButtonInputDriver") .setVersion(1) .setKeys(new int[] {KeyEvent.KEYCODE_SPACE}) .build(); }
Une fois que votre InputDriver
est initialisé, vous pouvez l'enregistrer avec le UserDriverManager
à l'aide de l'appel registerInputDriver()
.
UserDriverManager manager = UserDriverManager.getManager(); manager.registerInputDriver(mDriver);
Une fois que vous avez enregistré votre InputDriver
, votre service de pilote peut attendre que des événements lui soient envoyés à partir de votre classe d'implémentation de bouton. Si vous appuyez sur votre bouton personnalisé, vous pouvez notifier le service et créer un nouveau KeyEvent
, qui peut être placé sur le pipeline d'entrée Android à l'aide de la méthode emit(KeyEvent)
. Cette méthode renvoie true si KeyEvent
peut être envoyé à la structure Android et false si une erreur se produit.
if( buttonPressed ) { KeyEvent[] events = new KeyEvent[] {new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SPACE)}; if (!mDriver.emit(events)) { //something went wrong } }
La dernière chose que vous devrez faire est d'annuler l'enregistrement de votre objet InputDriver
à partir de UserDriverManager
lorsque votre application est terminée.
@Override public void onDestroy() { super.onDestroy(); UserDriverManager manager = UserDriverManager.getManager(); manager.unregisterInputDriver(mDriver); }
Écoute des événements d'entrée
Maintenant que vous êtes en mesure d'émettre des événements d'entrée de bouton pour le pipeline d'entrée Android, il est temps de les écouter. C'est là que tout le travail pour canaliser vos nouveaux événements de bouton dans le cadre Android est rentable. Dans l'activité de votre application, il vous suffit d'ajouter une méthode pour savoir quand un KeyEvent
est en panne, et un autre pour quand un KeyEvent
est en place. Dans ces méthodes, vous pouvez vérifier le code clé KeyEvent
et gérer l'événement de manière appropriée.
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if( event.getKeyCode() == KeyEvent.KEYCODE_SPACE ) { //handle it } return true; } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { return true; }
Pilotes de capteurs
Certains des composants les plus courants que vous utiliserez avec une table Android Things sont des capteurs. Comme Android dispose d'un cadre de capteurs assez robuste, il est logique que nous voulions être en mesure d'ajouter des données de nos composants externes dans ce pipeline.
Pour commencer, vous devrez créer une nouvelle classe Java qui interagit avec votre capteur matériel. Cette classe devra étendre UserSensorDriver
et implémenter la méthode read()
. En outre, si votre capteur prend en charge les modes d'économie d'énergie ou de veille, vous pouvez remplacer la méthode setEnabled()
et agir en conséquence.
L'extrait de code suivant est une version stubbed d'une classe de composant qui lirait des données via l'API d'E/S périphérique pour récupérer une valeur de données X, Y et Z et renvoyer un UserSensorReading
nouveau. Si les données ne sont pas disponibles, votre classe peut lancer une nouvelle IOException
.
public class ExampleSensorComponent extends UserSensorDriver { float x, y, z; @Override public UserSensorReading read() throws IOException{ try { // Read data from the sensor hardware and return it x = getXValueFromHardware(); y = getYValueFromHardware(); z = getZValueFromHardware(); return new UserSensorReading(new float[]{x, y, z}); } catch (Exception e) { // Error occurred reading the sensor hardware throw new IOException("Unable to read sensor"); } } //Used if supporting low power/sleep mode @Override public void setEnabled(boolean enabled) throws IOException { super.setEnabled(enabled); } }
Une fois votre classe de composant créée, vous pouvez créer un nouveau Service
qui l'instanciera, ainsi que de créer un nouvel objet UserSensor
et de le joindre à la pipeline de capteur Android.
Il existe deux types de capteurs que vous pouvez ajouter à ce pipeline. Les premiers sont des types prédéfinis, comme les gyroscopes, les accéléromètres, la lumière et la proximité, et peuvent être ajoutés au pipeline comme suit:
private ExampleSensorComponent mExampleSensor; private UserSensor mSensor; private SensorManager mSensorManager; @Override public void onCreate() { super.onCreate(); mExampleSensor = new ExampleSensorComponent(); mSensor = UserSensor.builder() .setName("ExampleSensorComponent") .setVendor("VendorName") .setType(Sensor.TYPE_ACCELEROMETER) .setDriver(mExampleSensor) .build(); UserDriverManager manager = UserDriverManager.getManager(); // Register the new driver with the framework manager.registerSensor(mSensor); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mSensorManager.registerDynamicSensorCallback(new SensorCallback()); } private class SensorCallback extends SensorManager.DynamicSensorCallback { @Override public void onDynamicSensorConnected(Sensor sensor) { //Sensor connected mSensorManager.registerListener(SensorDriverService.this, sensor, SensorManager.SENSOR_DELAY_NORMAL); } @Override public void onDynamicSensorDisconnected(Sensor sensor) { //Sensor disconnected mSensorManager.unregisterListener(SensorDriverService.this); } }
Vous remarquerez qu'un SensorManager.DynamicSensorCallback
est utilisé dans l'exemple ci-dessus. Cela permet d'avertir votre application lorsque le capteur est disponible pour le cadre, car l'enregistrement peut prendre un certain temps, de sorte que le cadre ne tente pas de lire les données d'un périphérique indisponible.



Le deuxième type est personnalisé, qui couvre tout ce qui n'est pas déjà pris en charge par Android. Quelques exemples incluent les niveaux de pH de l'eau, la vitesse du vent, la détection de mouvement ou tout autre chose que vous pouvez mesurer avec le nouveau matériel.
En remplaçant le paramètre constructeur setType()
par setCustomType()
, vous pouvez ajouter le nom de votre appareil et le mode de génération de rapports pour contrôler la façon dont il se déclenchera sur le pipeline.
mSensor = UserSensor.builder() .setName("ExampleSensorComponent") .setVendor("VendorName") .setType(Sensor.TYPE_ACCELEROMETER) .setCustomType(Sensor.TYPE_DEVICE_PRIVATE_BASE, "com.tutsplus.examplesensor", Sensor.REPORTING_MODE_ON_CHANGE) .setDriver(mExampleSensor) .build();
Enfin, lorsque votre application est terminée, vous devez annuler l'inscription de votre nouveau composant à partir de UserDriverManager
.
@Override public void onDestroy() { super.onDestroy(); UserDriverManager manager = UserDriverManager.getManager(); manager.unregisterSensor(mSensor); }
Conclusion
Dans ce tutoriel, vous avez appris comment prendre des composants construits à l'aide de l'API Peripheral E/S et les associer aux cadres Android appropriés pour les applications Android Things.
À ce stade de la série, vous avez tous les outils nécessaires pour créer des projets plus approfondis Android Things. En plus d'écrire vos propres pilotes, vous pouvez trouver des pilotes qui ont été écrits et les mettre en œuvre dans votre propre projet. Vous pouvez trouver la source de ces pilotes dans le dossier Android Things GitHub repo, ou consulter quelques exemples de travail à l'aide de ces pilotes.
Dans l'article suivant de cette série, nous allons aller un peu plus loin et créer un projet complet Android Things qui prend des photos d'une tarte aux framboises et les télécharge vers Firebase. Dans l'intervalle, consultez certains de nos autres tutoriels sur le développement d'applications Android ici sur Envato Tuts+!