Je vais dans ce tuto développer une classe listener(ecouteur).Cette classe permettra de détecter quand le téléphone est secoué(shake). Cette Fonctionnalité permet par exemple une mise à jour d’informations de vos applications juste en secouant le téléphone.
A vrai dire ce tuto sera juste un commentaire de texte. J’avais commencé à réfléchir comment implémenter cette fonctionnalité, et en cherchant sur le web je suis tombé sur l’excellent tuto de android.hlidskialf.com. Je vais donc juste expliquer la démarche qu’il a choisi.
Je crée une classe du type SensorListener .Cette classe vas détecter un shake de mon téléphone. La méthode qui m’intéresse dans cette classe est onSensorChanged. Cette méthode va détecter le déplacement du téléphone. Je vais la réécrire pour détecter un shake (secouement).
D’abord mes diiférentes variables
1 2 3 4 5 6 7 8 9 10 11 | public class CheckSecouer implements SensorEventListener { //vitesse minimun pour détecter un shake private static final int FORCE_THRESHOLD = 350; //temps minimun pour commencer a détecter la position du téléphone private static final int TIME_THRESHOLD = 100; //temps minimun entre 2 position pour être considérer comme un shaker private static final int SHAKE_TIMEOUT = 500; //temps entre un 2 shake pour incrementer le nombre de shake private static final int SHAKE_DURATION = 1000; // nombre de shake pour lancer une action private static final int SHAKE_COUNT = 3; |
Maintenant j’implémente ma fonction onSensorChanged qui détectera un shake (secouement)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public void onSensorChanged(SensorEvent event) { if (sensor != SensorManager.SENSOR_ACCELEROMETER) return; //le temps de debut long now = System.currentTimeMillis(); // si ce temps et le temps de la dernière position est trop long, supérieur à SHAKE_TIMEOUT on recommence avec mShakeCount = 0; if ((now - mLastForce) > SHAKE_TIMEOUT) { mShakeCount = 0; } if ((now - mLastTime) > TIME_THRESHOLD) { long diff = now - mLastTime; // calcule de la vitesse de shake float speed = Math.abs(values[SensorManager.DATA_X] + values[SensorManager.DATA_Y] + values[SensorManager.DATA_Z] - mLastX - mLastY - mLastZ) / diff * 10000; // on passe cette étape si notre vitesse est supérieure à notre vitesse minimum FORCE_THRESHOLD if (speed > FORCE_THRESHOLD) { // si nous avons un nombre de shake supérieur à notre nombre minimun SHAKE_COUNT if ((++mShakeCount >= SHAKE_COUNT) && (now - mLastShake > SHAKE_DURATION)) { mLastShake = now; mShakeCount = 0; if (mShakeListener != null) { // si toute les conditions sont réunies je lance ma fonction onshake dans laquelle j'ai l'action à exécuter mShakeListener.onShake(); } } mLastForce = now; } mLastTime = now; mLastX = values[SensorManager.DATA_X]; mLastY = values[SensorManager.DATA_Y]; mLastZ = values[SensorManager.DATA_Z]; } } |
Code source complet de la classe CheckSecouer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | package org.com.secouertelephone; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorListener; import android.hardware.SensorManager; public class CheckSecouer implements SensorEventListener { private static final int FORCE_THRESHOLD = 350; private static final int TIME_THRESHOLD = 100; private static final int SHAKE_TIMEOUT = 500; private static final int SHAKE_DURATION = 1000; private static final int SHAKE_COUNT = 3; private SensorManager mSensorMgr; private float mLastX=-1.0f, mLastY=-1.0f, mLastZ=-1.0f; private long mLastTime; private OnShakeListener mShakeListener; private Context mContext; private int mShakeCount = 0; private long mLastShake; private long mLastForce; public CheckSecouer(Context context) { mContext = context; resume(); // TODO Auto-generated constructor stub } public void setOnShakeListener(OnShakeListener listener) { mShakeListener = listener; } public void resume() { mSensorMgr = (SensorManager)mContext.getSystemService(Context.SENSOR_SERVICE); if (mSensorMgr == null) { throw new UnsupportedOperationException("Sensors not supported"); } boolean supported = mSensorMgr.registerListener(this, SensorManager.SENSOR_ACCELEROMETER, SensorManager.SENSOR_DELAY_GAME); if (!supported) { mSensorMgr.unregisterListener(this, SensorManager.SENSOR_ACCELEROMETER); throw new UnsupportedOperationException("Accelerometer not supported"); } } public void pause() { if (mSensorMgr != null) { mSensorMgr.unregisterListener(this, SensorManager.SENSOR_ACCELEROMETER); mSensorMgr = null; } } public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } public void onSensorChanged(SensorEvent event) { if (sensor != SensorManager.SENSOR_ACCELEROMETER) return; long now = System.currentTimeMillis(); if ((now - mLastForce) > SHAKE_TIMEOUT) { mShakeCount = 0; } if ((now - mLastTime) > TIME_THRESHOLD) { long diff = now - mLastTime; float speed = Math.abs(values[SensorManager.DATA_X] + values[SensorManager.DATA_Y] + values[SensorManager.DATA_Z] - mLastX - mLastY - mLastZ) / diff * 10000; if (speed > FORCE_THRESHOLD) { if ((++mShakeCount >= SHAKE_COUNT) && (now - mLastShake > SHAKE_DURATION)) { mLastShake = now; mShakeCount = 0; if (mShakeListener != null) { mShakeListener.onShake(); } } mLastForce = now; } mLastTime = now; mLastX = values[SensorManager.DATA_X]; mLastY = values[SensorManager.DATA_Y]; mLastZ = values[SensorManager.DATA_Z]; } } } |
Exemple d’utilisation de cette classe
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | public class Testy extends Activity{ // creer nom listener pour détecter des shakes private CheckSecouer mShaker; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //objet vibrator por faire une cation de vibration final Vibrator vibe = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE); //mon listener pour dététer un shake mShaker = new ShakeListener(this); mShaker.setOnShakeListener(new ShakeListener.OnShakeListener () { public void onShake() { //quand il y a détection je fais vibrer mon téléphone et j"ouvre un boite de dialogue vibe.vibrate(100); new AlertDialog.Builder(Testy.this) .setPositiveButton(android.R.string.ok, null) .setMessage("Secouer!") .show(); } } ); } @Override public void onResume() { mShaker.resume(); super.onResume(); } @Override public void onPause() { mShaker.pause(); super.onPause(); } } |













16 novembre 2009 à 18 h 12 min
Déjà essayé cet algo dans mon appli « Screen capture » sur le market.
Je l’ai enlevé car cela se déclenche intempestivement (par exemple en inclinant, pourtant doucement et légèrement, le téléphone de droite à gauche).
Pas au point ! Ou alors il faut jouer un peu avec les différents seuils
04 décembre 2009 à 17 h 03 min
Désolé mais ce code ne marche pas du tout…. à priori tu es parti du tuto dont tu fais référence pour le modifier et utiliser SensorEventListener sauf que tout le reste ne suit pas… dommage c’était un bon exemple et ça m’aurait bien servi !
04 décembre 2009 à 17 h 13 min
@ib@w à quelle endroit du tuto tu bloque ?
04 décembre 2009 à 17 h 21 min
méthode resume() , est-ce que c’est bien cela qu’il faut mettre :
boolean supported = mSensorMgr.registerListener(this, mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_GAME);
Pour le reste, je m’en sors. Par contre, aurais-tu une solution pour tester ce code à partir de l’émulateur ? Il y a bien SenseSimulator mais il fonctionne avec SensorListener qui est deprecated.
04 décembre 2009 à 17 h 27 min
dans la méthode resume(), est-ce bien cela qu’il faut mettre à la place : boolean supported = mSensorMgr.registerListener(this, mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_GAME);
Pour le reste je m’en sors. Par contre, aurais-tu une solution pour tester ce code sur l’émulateur ? il y a bien senseSimulator mais il utilise SensorListener (qui est deprecated).
04 décembre 2009 à 17 h 40 min
oops désolé pour le double post…
04 décembre 2009 à 17 h 44 min
@ib@w tu as quoi comme erreur dans ta fonction resune pour info ce tuto est pour une version 1.5 d’android si tu développes sur une version plus récente il faudrait peut être l’adapter un peu