Android, A Complete Course, From Basics to Enterprise Edition

Les Capteurs.

Android, A Complete Course, From Basics to Enterprise Edition. 1

Les Capteurs. 1

Communiquer avec le système. 1

1.1         Dialoguer avec les capteurs. 1

 Cet article est extraie du livre « Android, A Complete Course », disponible sur Android2ee.com.

Les exemples ou les programmes présents dans cet ouvrage sont fournis pour illustrer les descriptions théoriques. Ce code est libre de toute utilisation mais n'est pas distribuable.

La distribution du code est reservée au site :

http://android2ee.com.

La propriété intellectuelle du code appartient à :

Mathias Séguy

L’utilisation de ces codes est sous votre unique responsabilité et personne d’autre que vous ne pourra être tenu responsable des préjudices ou dommages de quelques natures que ce soit pouvant résulter de son utilisation.

Tous les noms de produits ou marques cités dans cet ouvrage sont des marques déposés par leurs propriétaires respectifs.

Publié par http://android2ee.com

Titre Original : Android, A Complete Course, From Basics to Enterprise Edition. Édition Française.

ISBN : 979-10-90388-00-0

Copyright © 2011 by Mathias Séguy

 

Aucune représentation ou reproduction, même partielle, autre que celles prévues à l’article L. 122-5 2° et 3° a) du code de la propriété intellectuelle ne peut être faite sans l’autorisation expresse de Mathias Seguy ou, le cas échéant, sans le respect des modalités prévues à l’article L. 122-10 dudit code

Communiquer avec le système

1.1       Dialoguer avec les capteurs

Les capteurs Android sont un nouvel axe d’interconnexion entre le monde et les applications.

Les capteurs référencés sont (et leur type associé se préfixant par Type_) :

·         L’accéléromètre (Accelerometer),

·         Le gyroscope (Gyroscope),

·         Le luxmètre (Light),

·         Le lecteur de champ magnétique (Magnetic_Field),

·         La boussole (Orientation),

·         Le baromètre (Pressure),

·         Le lecteur de proximité (Proximity),

·         Le thermomètre (Temperature).

Chacun de ces capteurs envoient des informations spécifiques à ses propres mesures, mais la gestion des capteurs est normalisée au moyen d’un même pattern.

Pour gérer les capteurs le SensorManager est la classe principale à utiliser.

Pour bien comprendre les données renvoyées par ces capteurs, la java doc est parfaite :

http://developer.android.com/reference/android/hardware/SensorManager.html

Et http://developer.android.com/reference/android/hardware/SensorEvent.html

 

1.1.1       Lister les capteurs présents

Pour lister ou récupérer un capteur particulier, il suffit d’instancier le SensorManager et ses méthodes getSensorList ou getDefaultSensor.

/** * The sensor manager */

SensorManager sensorManager;

 

/* * (non-Javadoc) *  * @see android.app.Activity#onCreate(android.os.Bundle) */

@Override

protected void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);

                // Instanciate the SensorManager

                sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

                // The find out which sensor are installed

                listSensor();

}

/* (non-Javadoc) * @see android.app.Activity#onPause() */

@Override

protected void onPause() {

                super.onPause();

                //Unregister your listener

}

 

 

/************************************************************************************/

/** List existing Sensors ****************************************************************/

/************************************************************************************/

/** * Find the list of all the sensor, find a specific sensor or find all the sensor of a specific type */

private void listSensor() {

                // First you can find all the sensors installed:

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

                // The associated string description

                StringBuffer sensorDesc = new StringBuffer();

                for (Sensor sensor : sensors) {

                               sensorDesc.append("New sensor detected : \r\n");

                               sensorDesc.append("\tName: " + sensor.getName() + "\r\n");

                               sensorDesc.append("\tType: " + getType(sensor.getType()) + "\r\n");

                               sensorDesc.append("Version: " + sensor.getVersion() + "\r\n");

                               sensorDesc.append("Resolution (in the sensor unit): " + sensor.getResolution() + "\r\n");

                               sensorDesc.append("Power in mA used by this sensor while in use" + sensor.getPower() +

"\r\n");

                               sensorDesc.append("Vendor: " + sensor.getVendor() + "\r\n");

                               sensorDesc.append("Maximum range of the sensor in the sensor's unit." +

sensor.getMaximumRange() + "\r\n");

                               sensorDesc.append("Minimum delay allowed between two events in microsecond"

+ " or zero if this sensor only returns a value when the data it's measuring changes"

                                                               + sensor.getMinDelay() + "\r\n");

                }

                Toast.makeText(this, sensorDesc.toString(), Toast.LENGTH_LONG).show();

                // Find a specific sensor:

                Sensor gyroscopeDefault = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

                // Find all the sensor of a specific type:

                List<Sensor> gyroscopes = sensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);

}

 

/**

 * @param type

 *            the integer type

 * @return the type as a string

 */

private String getType(int type) {

                String strType;

                switch (type) {

                case Sensor.TYPE_ACCELEROMETER: strType = "TYPE_ACCELEROMETER";break;

                case Sensor.TYPE_GRAVITY:strType = "TYPE_GRAVITY";break;

                case Sensor.TYPE_GYROSCOPE:  strType = "TYPE_GYROSCOPE";  break;

                case Sensor.TYPE_LIGHT:strType = "TYPE_LIGHT";break;

                case Sensor.TYPE_LINEAR_ACCELERATION:strType = "TYPE_LINEAR_ACCELERATION";

                               break;

                case Sensor.TYPE_MAGNETIC_FIELD:strType = "TYPE_MAGNETIC_FIELD";break;

                case Sensor.TYPE_ORIENTATION:strType = "TYPE_ORIENTATION";break;

                case Sensor.TYPE_PRESSURE:strType = "TYPE_PRESSURE";break;

                case Sensor.TYPE_PROXIMITY:     strType = "TYPE_PROXIMITY";   break;

                case Sensor.TYPE_ROTATION_VECTOR:    strType = "TYPE_ROTATION_VECTOR";break;

                case Sensor.TYPE_TEMPERATURE:strType = "TYPE_TEMPERATURE";break;

                default: strType = "TYPE_UNKNOW";break;

                }

                return strType;

}

 

 

1.1.2       Écouter les changements des données des capteurs

Pour cela, il suffit de créer un SensorEventListener et de l’enregistrer auprès du SensorManager

/** * The sensor manager */

SensorManager sensorManager;

/* * (non-Javadoc) *  * @see android.app.Activity#onCreate(android.os.Bundle) */

@Override

protected void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);

                // Instanciate the SensorManager

                sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

                // Define a sensor listener

                implementSensorListener();

}

/* (non-Javadoc) * @see android.app.Activity#onPause() */

@Override

protected void onPause() {

                super.onPause();

                //Unregister your listener

}

/**************************************************************************************/

/** SensorListener ***********************************************************************/

/**************************************************************************************/

private void implementSensorListener() {

                // First define the sensor you want to listen (you can listen for a bunch of sensors)

                final Sensor listenedSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);

                // Then define your Listener

                final SensorEventListener sensorOrientationListener = new SensorEventListener() {

                               @Override

                               public void onSensorChanged(SensorEvent event) {

                                               // First insure you are listening the right sensor

                                               if (event.sensor.equals(listenedSensor)) {

                                                               // Find the associated accuracy

                                                               int accuracy = event.accuracy;

                                                               switch (accuracy) {

                                                               case SensorManager.SENSOR_STATUS_ACCURACY_LOW:

                                                               case SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM:

                                                               case SensorManager.SENSOR_STATUS_ACCURACY_HIGH:

                                                               case SensorManager.SENSOR_STATUS_UNRELIABLE:

                                                               default: break;

                                                               }

                                                               // Find the timestamp in nanosecond

                                                               long timestamp = event.timestamp;

                                                               // Retrieve the associated values (cf javadoc)

                                                               float[] val = event.values;

                                                               //do something with those informations

                                               }

                               }

                               @Override

                               public void onAccuracyChanged(Sensor sensor, int accuracy) {

                                               // First insure you are listening the right sensor

                                               if(sensor.equals(listenedSensor)){

                                                               switch (accuracy) {

                                                               case SensorManager.SENSOR_STATUS_ACCURACY_LOW:

                                                               case SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM:

                                                               case SensorManager.SENSOR_STATUS_ACCURACY_HIGH:

                                                               case SensorManager.SENSOR_STATUS_UNRELIABLE:

                                                               default:

                                                                              break;

                                                               }

                                                               //do something with those informations

                                               }

                               }

                };

                //Register your sensor Listener in the sensorManager:

                //Choose the rate: The defaukt rate

                int rate=SensorManager.SENSOR_DELAY_NORMAL;

                //the rate to use for Games

                 rate=SensorManager.SENSOR_DELAY_GAME;

                 //the fastest rate that can be set

                 rate=SensorManager.SENSOR_DELAY_FASTEST;

                 //The rate to use to update the UI

                 rate=SensorManager.SENSOR_DELAY_UI;

                 //And then register

                sensorManager.registerListener(sensorOrientationListener, listenedSensor, rate);

}

 

 

1.1.3       Utiliser les données renvoyées par les capteurs

Chaque capteur renvoie un vecteur de données sous forme de flottant (ce vecteur peut être d’une à trois dimensions).

Le tableau ci-dessous synthétise la sémantique associée à ses vecteurs :

Nom

Dimension du vecteur

Unité

Sémantique

Values[]

Accelerometer

3

m/s2

Mesure de l’accélération (gravité incluse)

[0] axe x

[1] axe y

[2] axe z

Gyroscope

3

Radian/second

Mesure la rotation en termes de vitesse autour de chaque axe

[0] vitesse angulaire autour de x

[1] vitesse angulaire autour de y

[2] vitesse angulaire autour de z

Light

1

Lux

Mesure de la luminosité

[0]valeur

Magnetic_Field

3

µTesla

Mesure du champ magnétique

[0] axe x

[1] axe y

[2] axe z

Orientation

3

degrès

Mesure l’angle entre le nord magnétique

[0] Azimut entre l’axe y et le nord

[1] Rotation autour de l’axe x (-180,180)

[2] Rotation autour de l’axe y (-90,90)

Pressure

1

KPascal

Mesure la pression

[0]valeur

Proximity

1

mètre

Mesure la distance entre l’appareil et un objet cible

[0]valeur

Temperature

1

Celsius

Mesure la température

[0]valeur

 

Pour utiliser certains de ces capteurs un minimum de connaissance en physique est nécessaire.

1.1.4       Utilisation du thermomètre, baromètre et luxmètre

Il n’y a rien de miraculeux, le code ci-dessous vous présente cette utilisation.

/** * The sensor manager */

SensorManager sensorManager;

/* * (non-Javadoc) *  * @see android.app.Activity#onCreate(android.os.Bundle) */

@Override

protected void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);

                // Instanciate the SensorManager

                sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

                //temperaturePressureAndLight

                simpleSensors();

}

/* (non-Javadoc) * @see android.app.Activity#onPause() */

@Override

protected void onPause() {

                super.onPause();

                //Unregister your listener

}

/*****************************************************************************************/

/** Simple sensors **************************************************************************/

/*****************************************************************************************/

/**

 * We suppose Temperature, Pressure and Light are on the device.

 * This method shows how to use them

 */

private void simpleSensors(){

                // First define the sensor you want to listen (you can listen for a bunch of sensors)

                final Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);

                final Sensor temperatureSensor = sensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE);

                final Sensor pressureSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);

                // Then define your Listener

                final SensorEventListener sensorOrientationListener = new SensorEventListener() {

                               @Override

                               public void onSensorChanged(SensorEvent event) {

                                               // First insure you are listening the right sensor

                                               if (event.sensor.equals(lightSensor)) {

                                                               lightChanged(event.values[0]);

                                               }else if(event.sensor.equals(temperatureSensor)) {

                                                               temperatureChanged(event.values[0]);

                                               }else if(event.sensor.equals(pressureSensor)) {

                                                               pressureChanged(event.values[0]);

                                               }

                               }

 

                               @Override

                               public void onAccuracyChanged(Sensor sensor, int accuracy) {

                                                               //don't care something with those informations

                               }

                };

                //Register your sensor Listener in the sensorManager:

                //Choose the rate: The defaukt rate

                int rate=SensorManager.SENSOR_DELAY_UI;

                 //And then register

                sensorManager.registerListener(sensorOrientationListener, lightSensor, rate);

                sensorManager.registerListener(sensorOrientationListener, temperatureSensor, rate);

                sensorManager.registerListener(sensorOrientationListener, pressureSensor, rate);

}

/** * @param value */

private void lightChanged(float value){

                 //You can use the Sensor Manager to know the intensity in human words

                if(value<SensorManager.LIGHT_NO_MOON){}

                else if(value<SensorManager.LIGHT_FULLMOON){}

                else if(value<SensorManager.LIGHT_CLOUDY){}

                else if(value<SensorManager.LIGHT_SUNRISE){}

                else if(value<SensorManager.LIGHT_OVERCAST){}

                else if(value<SensorManager.LIGHT_SHADE){}

                else if(value<SensorManager.LIGHT_SUNLIGHT){}

                else if(value<SensorManager.LIGHT_SUNLIGHT_MAX){}

                else{}

                Toast.makeText(this, "new luminosity :"+value+" lux", Toast.LENGTH_SHORT).show();

}

/** * @param value */

private void temperatureChanged(float value){

                Toast.makeText(this, "new temperature :"+value+"°C", Toast.LENGTH_SHORT).show();

}

/** * @param value */

private void pressureChanged(float value){

                Toast.makeText(this, "new pressure :"+value+"°KP (KiloPascal)", Toast.LENGTH_SHORT).show();

}

 

 

1.1.5       Utilisation de l’accéléromètre, du gyroscope et de la boussole

Mettez vous à la physique, ici, le problème n’est pas l’informatique mais la physique sous-jacente que vous allez manipuler.

L’accéléromètre permet de mesurer le champ d’accélération qui entoure l’appareil. Ce champ étant tridimensionnel, les valeurs sont renvoyées sous forme d’un vecteur (x,y,z). À partir de l’accélération, vous ne pouvez détecter directement le vecteur vitesse. Pour cela, vous devez obtenir une vitesse référence (aucun mouvement) puis recalculer votre vitesse courante en utilisant les valeurs de l’accéléromètre et le temps entre deux mesures.

Remarque : si l’accéléromètre est suffisamment précis, vous pouvez connaitre l’altitude grâce à lui : Altitude=  ou RT est le rayon terrestre (6378 103), g0 la valeur de g à l’équateur (9.79m.s-2) et g la valeur mesurée. En même temps, la méthode getAltitude du SensorManager effectue déjà le travail pour vous, mais à partir de la pression.

Remarque : L’exemple Android suivant montre une application où des billes sont dirigées par l’accéléromètre. http://developer.android.com/resources/samples/AccelerometerPlay/src/com/example/android/accelerometerplay/AccelerometerPlayActivity.html