Använda Accelerometer på Android

I denna handledning kommer vi att undersöka hur man använder accelerometern, en av de många hårdvarnosensorerna för moderna smartphones, i en Android-applikation. Jag ska förklara vad en accelerometer är och varför det kan vara något du vill dra nytta av i dina Android-applikationer.

Introduktion

Före början av smartphones kunde en av de få maskinvarukomponenterna interagera med tangentbordet. Men tiderna har förändrats och interagerar med hårdvarukomponenter blir allt vanligare.

Att använda gester känns ofta mer naturligt än att interagera med ett användargränssnitt genom mus och tangentbord. Detta gäller särskilt för enheter som berör smartphones och tabletter. Jag tycker att användandet av gester kan ge en Android-applikation till liv, vilket gör det mer intressant och spännande för användaren.

Helt få apps använder nu accelerometern. Titta till exempel på dessa appmallar på Envato Market, som inkluderar ett racingspel och ett slumpmässigt antal shaker.

I den här handledningen använder vi en gest som du hittar i ett flertal mobilapplikationer, skakningsbenen. Vi använder skaka gesten för att slumpmässigt generera sex lotteri nummer och visa dem på skärmen med en ganska animering.

1. Komma igång

Steg 1: Projektinställningar

Starta ett nytt Android-projekt i din favorit IDE (Integrated Development Environment) för Android-utveckling. För denna handledning använder jag IntelliJ IDEA.

Om din IDE stöder Android-utveckling, har den skapat en Huvudsaklig klass för dig. Namnet på den här klassen kan variera beroende på vilken IDE du använder. De Huvudsaklig klassen spelar en nyckelroll när din ansökan lanseras. Din IDE ska också ha skapat en huvudlayoutfil som Huvudsaklig klassanvändningar för att skapa applikationens användargränssnitt.

Eftersom vi ska använda en shake gest, är det en bra idé att låsa enhetens orientering. Detta kommer att se till att applikationens användargränssnitt inte ständigt växlar mellan porträtt och landskap. Öppna projektets manifestfil och ställ in skärmorientering alternativ till porträtt.

     

Steg 2: Ställa in sensorn

Med vårt projekt inrättat är det dags att få händerna smutsiga och skriva lite kod. För närvarande har huvudaktivitetsklassen en onCreate Metod där vi bestämmer huvudlayouten genom att åberopa setContentView enligt nedanstående.

public class Main utökar aktivitet / ** kallas när aktiviteten skapas först. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); 

Beroende på vilken IDE du använder kan du behöva lägga till några importdeklarationer till Main.java, filen där din Huvudsaklig klass liv. De flesta IDE: er kommer att infoga dessa importdeklarationer för dig, men jag vill se till att vi är på samma sida innan vi fortsätter. Den första importdeklarationen, importera android.app.Activity, importera Aktivitet klass medan den andra importdeklarationen, importera android.os.Bundle, importera Bunt klass. Den tredje importen, com.example.R, innehåller definitionerna för resurserna i ansökan. Denna importdeklaration skiljer sig från den som du ser nedan eftersom det beror på namnet på ditt paket.

importera android.app.Activity; importera android.os.Bundle; importera com.example.R;

I nästa steg utnyttjar vi SensorEventListener gränssnitt, som deklareras i Android SDK. Att använda SensorEventListener gränssnitt, Huvudsaklig Aktivitetsklassen behöver implementera den som visas i kodfliken nedan. Om du tittar på den uppdaterade Huvudsaklig aktivitetsklass, hittar du att jag använder redskap sökord för att berätta för kompilatorn att Huvudsaklig klassen implementerar SensorEventListener gränssnitt.

public class Main utökar Aktivitet implementerar SensorEventListener / ** Kallas när aktiviteten skapas först. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); 

Att använda SensorEventListener gränssnitt, måste du lägga till ett annat importdeklaration enligt nedan. De flesta IDE: erna kommer intelligent att lägga till importdeklarationen för dig, så du behöver nog inte oroa dig för det här.

importera android.hardware.SensorEventListener;

Från det ögonblick uppdaterar du Huvudsaklig klass implementering som visas ovan kommer du att se några fel dyker upp. Detta är inte förvånande eftersom vi behöver två implementera två nödvändiga metoder för SensorEventListener gränssnitt.

Om du använder IntelliJ IDEA, bör du uppmanas att lägga till dessa nödvändiga metoder när du klickar på felet. Om du använder en annan IDE kan detta beteende vara annorlunda. Låt oss lägga till de två nödvändiga metoderna för hand som visas i kodfliken nedan. Se till att du lägger till dessa metoder i Huvudsaklig klass och utanför onCreate metod.

@Override public void onSensorChanged (SensorEvent event)  @Override public void on AccuracyChanged (Sensorsensor, int noggrannhet) 

Låt oss ta en titt på onSensorChanged metod. Vi kommer att använda den här metoden för att upptäcka shake gesten. De onSensorChanged Metoden åberopas varje gång den inbyggda sensorn upptäcker en förändring. Denna metod aktiveras upprepade gånger när enheten är i rörelse. Att använda Sensor och SensorEvent klasser lägger vi till ytterligare två importdeklarationer enligt nedan.

importera android.hardware.Sensor; importera android.hardware.SensorEvent;

Innan vi genomför onSensorChanged, Vi måste deklarera två privata variabler i Huvudsaklig klass, senSensorManager av typ SensorManager och senAccelerometer av typ Sensor.

privat SensorManager senSensorManager; Privat Sensor SenAccelerometer;

De SensorManager klassen deklareras i android.hardware.SensorManager. Om du ser några fel dyker upp, dubbelkontrollera att SensorManager klassen importeras också.

importera android.hardware.SensorManager;

I onCreate metod, vi initierar de variabler som vi just har deklarerat och registrerar en lyssnare. Ta en titt på den uppdaterade implementeringen av onCreate metod.

@Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); senSensorManager = (SensorManager) getSystemService (Context.SENSOR_SERVICE); senAccelerometer = senSensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER); senSensorManager.registerListener (detta, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 

För att initiera SensorManager Exempel, vi åberopar getSystemService för att hämta systemets SensorManager exempel som vi i sin tur använder för att komma åt systemets sensorer. De getSystemService Metoden används för att få en hänvisning till en tjänst av systemet genom att skicka tjänstens namn. Med sensorchefen till vårt förfogande, får vi en referens till systemets accelerometer genom att åberopa getDefaultSensor på sensorhanteraren och passera typen av sensor som vi är intresserade av. Vi registrerar sedan sensorn med hjälp av en av SensorManagers offentliga metoder, registerListener. Denna metod accepterar tre argument, aktivitetens sammanhang, en sensor och hur mycket sensorns händelser levereras till oss.

offentlig klass Huvudsaklig utökar Aktivitet implementerar SensorEventListener privat SensorManager senSensorManager; Privat Sensor SenAccelerometer; / ** Kallas när aktiviteten skapas först. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); senSensorManager = (SensorManager) getSystemService (Context.SENSOR_SERVICE); senAccelerometer = senSensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER); senSensorManager.registerListener (detta, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);  @Override public void onSensorChanged (SensorEvent sensorEvent)  @Override public void on AccuracyChanged (Sensorsensor, int noggrannhet) 

Det finns två andra metoder som vi måste överväga, onPause och på CV. Dessa är metoder för Huvudsaklig klass. Det är bra att avregistrera sensorn när applikationen är viloläge och registrera sensorn igen när programmet återupptas. Kolla koden nedan för att få en uppfattning om hur det fungerar i praktiken.

skyddad tomgång onPause () super.onPause (); senSensorManager.unregisterListener (detta); 
skyddad tomrum påResume () super.onResume (); senSensorManager.registerListener (detta, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 

Steg 3: Upptäcka Shake Gesture

Vi kan nu börja fokusera på köttet i ansökan. Det kommer att kräva lite matematik för att räkna ut när en skakningsbehållning äger rum. Det mesta av logiken kommer att gå in i onSensorChanged metod. Vi börjar med att förklara några variabler i vår Huvudsaklig klass. Ta en titt på kodfliken nedan.

privat long lastUpdate = 0; privat float last_x, last_y, last_z; privat statisk slutlig int SHAKE_THRESHOLD = 600;

Låt oss nu zooma in på implementeringen av onSensorChanged metod. Vi tar en hänvisning till Sensor exempel med hjälp av SensorEvent exempel som skickas till oss. Som du kan se i kodfliken nedan, dubbelklickar vi på att vi får en referens till rätt sensortyp, systemets accelerometer.

Offentlig tomgång på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; om (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) 

Nästa steg är att extrahera enhetens position i rymden, x, y, och z axel. Ta en titt på bilden nedan för att bättre förstå vad jag hänvisar till. De x axeln definierar lateral rörelse, medan y axeln definierar vertikal rörelse. De z axeln är lite svårare eftersom den definierar rörelse in och ut ur planet definierat av x och y axlar.


För att få värdena för varje axel, frågar vi sensorhändelsen för dess värden som visas nedan. Händelserna värden attributet är en uppsättning floats.

Offentlig tomgång på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; om (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; 

Systemets sensorer är otroligt känsliga. När du håller en enhet i handen, är den ständigt i rörelse, oavsett hur stabil din hand är. Resultatet är att onSensorChanged Metoden åberopas flera gånger per sekund. Vi behöver inte alla dessa data så vi måste se till att vi bara provar en delmängd av de data vi får från enhetens accelerometer. Vi lagrar systemets nuvarande tid (i millisekunder) förvara den i CURTIME och kontrollera om mer än 100 millisekunder har gått sedan senaste gången onSensorChanged åberopades.

Offentlig tomgång på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; om (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; lång curTime = System.currentTimeMillis (); om ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; 

Det sista stycket av pusset är att upptäcka om enheten har skakats eller inte. Vi använder Matematik klass för att beräkna enhetens hastighet som visas nedan. Den statiskt deklarerade SHAKE_THRESHOLD variabel används för att se huruvida en skakningsbeakt har detekterats eller inte. Ändra SHAKE_THRESHOLD ökar eller minskar känsligheten så känner du dig fri att spela med sitt värde.

Offentlig tomgång på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; om (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; lång curTime = System.currentTimeMillis (); om ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; flythastighet = Math.abs (x + y + z - last_x - last_y - last_z) / diffTime * 10000; om (hastighet> SHAKE_THRESHOLD)  last_x = x; last_y = y; last_z = z; 

2. Avsluta lotteriprogrammet

Vi har nu en applikation som kan upptäcka en shake gest med accelerometern. Låt oss avsluta det här projektet med hjälp av skakningsbehållningen för att välja sex slumpartier. Jag ska visa dig hur man genererar ett slumptal mellan 1 och 49, men du är fri att ändra mitt genomförande för att få det att fungera med hur lotteriet spelas i ditt land.

Låt oss börja med att ställa in programmets huvudlayoutfil som vi ska använda för användargränssnittet. Som du kan se nedan använder jag sex ramlayouter med bakgrund av en bild av en boll.

                        

Varje ramlayout innehåller en textvy som visar ett slumpmässigt genererat lotteri nummer. Observera att varje ramlayout och textvy har en id för att se till att vi kan referera dem senare.

Med huvudinställningen redo att använda, låt oss återkomma Huvudsaklig klass. Vi börjar med att skapa getRandomNumber, en privat metod för att generera sex slumptal mellan 1 och 49.

privat tomt getRandomNumber () ArrayList numbersGenerated = new ArrayList (); för (int i = 0; i < 6; i++)  Random randNumber = new Random(); int iNumber = randNumber.nextInt(48) + 1; if(!numbersGenerated.contains(iNumber))  numbersGenerated.add(iNumber);  else  i--;   

Vi skapar först en Arraylist Exempel, som vi använder för att lagra de sex siffrorna i. I varje slinga av för loop, vi utnyttjar Java Slumpmässig klass för att generera ett slumptal. För att se till att vi får ett nummer mellan 1 och 49, vi lägger till 1 till resultatet. Nästa steg är att kontrollera om det genererade numret redan finns i matrislistan, eftersom vi bara vill ha unika nummer i matrislistan.

Observera att det kan vara nödvändigt att lägga till ytterligare två importdeklarationer för att hålla kompilatorn glad.

importera java.util.ArrayList; importera java.util.Random;

Det sista steget är att visa det slumpmässigt genererade numret i användargränssnittet. Vi får en hänvisning till de textvyer vi skapade tidigare och fyller i varje textvisning med ett slumpmässigt nummer. Vi lägger också till en snygg animation till ramlayouterna, men gärna avbryta eller ändra animeringen.

privat tomt getRandomNumber () ArrayList numbersGenerated = new ArrayList (); för (int i = 0; i < 6; i++)  Random randNumber = new Random(); int iNumber = randNumber.nextInt(48) + 1; if(!numbersGenerated.contains(iNumber))  numbersGenerated.add(iNumber);  else  i--;   TextView text = (TextView)findViewById(R.id.number_1); text.setText(""+numbersGenerated.get(0)); text = (TextView)findViewById(R.id.number_2); text.setText(""+numbersGenerated.get(1)); text = (TextView)findViewById(R.id.number_3); text.setText(""+numbersGenerated.get(2)); text = (TextView)findViewById(R.id.number_4); text.setText(""+numbersGenerated.get(3)); text = (TextView)findViewById(R.id.number_5); text.setText(""+numbersGenerated.get(4)); text = (TextView)findViewById(R.id.number_6); text.setText(""+numbersGenerated.get(5)); FrameLayout ball1 = (FrameLayout) findViewById(R.id.ball_1); ball1.setVisibility(View.INVISIBLE); FrameLayout ball2 = (FrameLayout) findViewById(R.id.ball_2); ball2.setVisibility(View.INVISIBLE); FrameLayout ball3 = (FrameLayout) findViewById(R.id.ball_3); ball3.setVisibility(View.INVISIBLE); FrameLayout ball4 = (FrameLayout) findViewById(R.id.ball_4); ball4.setVisibility(View.INVISIBLE); FrameLayout ball5 = (FrameLayout) findViewById(R.id.ball_5); ball5.setVisibility(View.INVISIBLE); FrameLayout ball6 = (FrameLayout) findViewById(R.id.ball_6); ball6.setVisibility(View.INVISIBLE); Animation a = AnimationUtils.loadAnimation(this, R.anim.move_down_ball_first); ball6.setVisibility(View.VISIBLE); ball6.clearAnimation(); ball6.startAnimation(a); ball5.setVisibility(View.VISIBLE); ball5.clearAnimation(); ball5.startAnimation(a); ball4.setVisibility(View.VISIBLE); ball4.clearAnimation(); ball4.startAnimation(a); ball3.setVisibility(View.VISIBLE); ball3.clearAnimation(); ball3.startAnimation(a); ball2.setVisibility(View.VISIBLE); ball2.clearAnimation(); ball2.startAnimation(a); ball1.setVisibility(View.VISIBLE); ball1.clearAnimation(); ball1.startAnimation(a); 

Vi måste lägga till några fler importdeklarationer för att göra allt detta. Ta en titt på kodfliken nedan.

importera android.view.View; importera android.view.animation.Animation; importera android.view.animation.AnimationUtils; importera android.widget.FrameLayout; importera android.widget.TextView;

När det gäller animationerna, ta en titt på innehållet i animationsfilen nedan. Observera att du måste skapa en anim mapp i projektets resurs katalog och namnge den move_down_ball_first.xml. Genom att justera värdena på skala element, kan du ändra animationens varaktighet och positionen för varje boll.

   

Allt som finns kvar för oss att göra är att ringa getRandomNumber i onSensorChanged i Huvudsaklig klass. Ta en titt på det fullständiga genomförandet av onSensorChanged visas nedan.

Offentlig tomgång på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; om (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; lång curTime = System.currentTimeMillis (); om ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; flythastighet = Math.abs (x + y + z - last_x - last_y - last_z) / diffTime * 10000; om (hastighet> SHAKE_THRESHOLD) getRandomNumber ();  last_x = x; last_y = y; last_z = z; 

Slutsats

I den här handledningen har jag visat hur accelerometern fungerar och hur du kan använda den för att upptäcka en shake gest. Naturligtvis finns det många andra användningsfall för accelerometern. Med en grundläggande förståelse för att upptäcka gester med hjälp av accelerometern uppmuntrar jag dig att experimentera med accelerometern för att se vad du kan göra med det.

Om du arbetar mycket med Android-utveckling kommer du förmodligen att springa över situationer där du behöver hjälp med en viss aspekt som inte är din specialitet. Om så är fallet, försök att anställa en av expertappsutvecklare på Envato Studio för att slutföra arbetet snabbt och pålitligt.