Android La sa va rden fra n sensorer Notera att detta endast är en introduktion och inte fullständiga instruktioner. För att komma vidare på egen hand kan du följa de länkar till texter som anges. Sensorer i smart phones och liknande enheter En smart phone eller tablet är idag utrustad med en uppsättning inbyggda sensorer. Exempel på vanliga sensorer idag är Accelerometer (acceleration/gravitation) Gyroskop (rotationshastighet, rad/s) Magnetometer Ljus, IR m.m., ex. fotodioder Tryck (atmosfärs-) Temperatur Dessutom finns ofta mjukvara för att kombinera flera sensorer för att få ut ny information; t.ex. kan värden från accelerometer, gyroskop och magnetometer kombineras för att ge information om hur enheten är orienterad i rummet (en s.k. virtuell sensor). SensorEventListener För att läsa av värden som en sensor genererar måste man skriva en lyssnarklass och koppla ett objekt av denna lyssnarklass till en specifik sensor, dvs. liknande som när du vill lyssna på om användaren tryckt på en knapp (men i detta fall implementerar du ett interface som heter SensorEventListener). Detta görs i applikationens aktivitet och lyssnarklassen kan t.ex. se ut så här: private class AccelerometerListener implements SensorEventListener { public void onsensorchanged(sensorevent event) { float x = event.values[0]; float y = event.values[1]; float z = event.values[2]; long t = event.timestamp; // milli seconds // Do something with the information Vad värdena i event.values (en s.k. array av data; här flyttal, float) står för beror på vilken typ av sensor vi lyssnar på (informationen finns i dokumentationen på developer.android.com). För en accelerometer representerar värdena respektive accelerationen i x-led, y-led och z-led, se figur 1 för definition av riktningarna.
Figur 1 Koordinatsystem för accelerometer, relativt enheten. Källa http://developer.android.com. Registrera och avregistrera en SensorEventListener Registrera lyssnare För att få tillgång till en specifik sensor, och koppla en lyssnare till denna, använder vi oss av enhetens SensorManager, se nedan. sensormanager = (SensorManager) getsystemservice(context.sensor_service); Sensor accelerometer = sensormanager.getdefaultsensor(sensor.type_accelerometer); sensormanager.registerlistener(accelerometerlistener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL); Den sensortyp som anges kan t.ex. vara Sensor.TYPE_ACCELEROMETER TYPE_GRAVITY (virtuell) TYPE_LINEAR_ACCELERATION (virtuell) TYPE_GYROSCOPE TYPE_ORIENTATION (compound, virtuell) TYPE_ROTATION_VECTOR (virtuell) TYPE_LIGHT TYPE_MAGNETIC_FIELD TYPE_PRESSURE Det delay som anges när man registrerar lyssnaren anger ungefärligt hur ofta lyssnaren ska ta emot värden från sensorn. Standardvärden är: SensorManager.SENSOR_DELAY_NORMAL ( 5 Hz) SENSOR_DELAY_UI SENSOR_DELAY_GAME ( 50 Hz) SENSOR_DELAY_FASTEST
Avregistrera en lyssnare Eftersom en lyssnare som registrerats på en sensor förbrukar resurser (batteri, CPU-tid m.m.) bör man avregistrera lyssnaren så snart vi inte behöver sensor-data längre. Avregistreringen av lyssnaren görs så här: if (sensormanager!= null) { sensormanager.unregisterlistener(accelerometerlistener); Testa själv Testkör projektet AccelerometerExample och studera hur värdena varierar när telefonens orientering i rummet ändras (de värden som visas är [a x, a y och a z ]). Vad representerar värdet på a z när telefonen ligger på en horisontell yta? Studera lyssnarklassen samt koden för att registrera och avregistrera lyssnaren. Man bör avregistrera lyssnaren då applikationen inte är aktiv längre, dvs. då aktiviteten inte längre är den som användaren ser längst fram på skärmen (då behöver vi i de flesta fallen inte längre data från sensorn). Det är det som görs i metoderna onpause och onpause i aktiviteten; dessa metoder anropas när aktiviten lämnar fokus, respektive alldeles innan den hamnar i fokus igen. Vill du veta mer om hur man programmerar med sensorer i Android kan du läsa här: http://developer.android.com/guide/topics/sensors/sensors_overview.html Snake revisited Utgå från projektet SnakeWithAccelerometer. Detta projekt innehåller all kod som behövs för att läsa värden från accelerometern, men du måste själv lägga till hur du ska använda värdena (ax,ay,az) för att styra ormen. I klassen MainActivity finns kod för lyssnarklassen, AccelerometerListener. Det är i metoden onsensorchanged, som kommer att anropas när det finns ett nytt sensorvärde, som du skriver koden som tolkar sensorvärdena och därefter ändrar ormens riktning. Metoderna startlistening och stoplistening innehåller kod för att registrera lyssnaren respektive avregistrera denna när den inte behövs längre. Dessa metoder anropas i onresume respektive onpause som exekveras automatiskt då applikationen visas respektive döljs av andra applikationer. Du behöver inte ändra i denna kod. Testa själv Lägg till att användaren kan styra ormens riktning genom att luta skärmen. Gå till metoden onsensorchanged i MainActivity. Kontrollera om accelerationen längs x-axeln är större än något värde, t.ex. 2,0 m/s 2, och ändra i så fall riktningen på masken till WEST (eller till EAST? du behöver fundera eller testa för att veta vilket). Du ändrar maskens riktning med snakemodel.setdirection(direction.west/east/north eller SOUTH) Gör sedan på samma sätt med accelerationen i y-led (NORTH eller SOUTH). Kör du fast finns ett lösningsförslag längst bak i detta dokument.
Förbättra också spelet så att ett nytt äpple slumpas ut så fort ormen ätit ett och att ormen växer med ett segment när den ätit ett äpple (se instruktionerna i dokumentet Android Rita och touch events ).
Lösningsförslag SensorEventListener för Snake Denna kod läser av accelerationen i enhetens x- och y-led (se figur 1 för referens) och ändrar ormens riktning om värdet överstiger ett tröskelvärde (THRESHOLD, du får testa dig fram till lämpligt värde). För att komma åt SnakeModel i aktiviteten (jag ska ju ev. ändra ormens riktning) använder jag metoden snakview.getsnakemodel (som finn i klassen SnakeView). private class AccelerometerListener implements SensorEventListener { private final float ACC_THRESHOLD = 2.0F; public void onsensorchanged(sensorevent event) { double ax = event.values[0]; double ay = event.values[1]; double az = event.values[2]; long time = event.timestamp; //Log.i("SnakeSensor", "(" + x + "," + y + "," + z + ")"); //Log.i("SnakeSensor", "timestamp: " + time); SnakeModel snakemodel = snakeview.getsnakemodel(); if(ay > ACC_THRESHOLD) { Log.i("SnakeSensor", "South down"); snakemodel.setdirection(direction.south); else if(ay < -ACC_THRESHOLD) { Log.i("SnakeSensor", "North down"); snakemodel.setdirection(direction.north); if(ax > ACC_THRESHOLD) { Log.i("SnakeSensor", "West down"); snakemodel.setdirection(direction.west); else if(ax < -ACC_THRESHOLD) { Log.i("SnakeSensor", "East down"); snakemodel.setdirection(direction.east); public void onaccuracychanged(sensor sensor, int accuracy) { // Du måste naturligtvis även registrera lyssnaren (samt avregistrera den när den inte längre behövs, t.ex. när spelet är över).