I denne opplæringen skal vi undersøke hvordan du bruker accelerometeret, en av de mange maskinvaresensorene til moderne smartphones, i en Android-applikasjon. Jeg skal forklare hva en akselerometer er, og hvorfor det kan være noe du vil benytte deg av i Android-applikasjonene dine.
Før begynnelsen av smarttelefoner kunne en av de få maskinvarekomponentene samhandle med tastaturet. Men tider har endret seg og interaksjon med maskinvarekomponenter blir stadig mer vanlige.
Bruk av bevegelser føles ofte naturligere enn å interagere med et brukergrensesnitt gjennom mus og tastatur. Dette gjelder spesielt for berøringsenheter, for eksempel smarttelefoner og nettbrett. Jeg finner at bruk av bevegelser kan bringe en Android-applikasjon til liv, noe som gjør den mer interessant og spennende for brukeren.
En hel del apps bruker nå akselerometeret. For eksempel, se på disse appmaler på Envato Market, som inkluderer et raceringsspill og en tilfeldig nummerrister.
I denne opplæringen bruker vi en gest som du finner i ganske mange mobile applikasjoner, ristbevegelsen. Vi bruker shake gestus til å tilfeldig opprette seks lotteri tall og vise dem på skjermen ved hjelp av en pen animasjon.
Start et nytt Android-prosjekt i din favoritt IDE (Integrated Development Environment) for Android-utvikling. For denne opplæringen bruker jeg IntelliJ IDEA.
Hvis IDE støtter Android-utvikling, har den opprettet en Hoved
klasse for deg. Navnet på denne klassen kan variere avhengig av hvilken IDE du bruker. De Hoved
klassen spiller en nøkkelrolle når søknaden din blir lansert. Din IDE bør også ha opprettet en hovedoppsettfil som Hoved
klassen bruker til å lage applikasjonens brukergrensesnitt.
Siden vi skal bruke en shake gest, er det en god idé å låse enhetens orientering. Dette vil sikre at applikasjonens brukergrensesnitt ikke skifter hele tiden mellom portrett og landskap. Åpne prosjektets manifestfil og sett inn Skjermretning
alternativ til portrett
.
Med vårt prosjekt satt opp, er det på tide å få hendene skitne og skrive noen kode. For øyeblikket har hovedaktivitetsklassen en onCreate
Metode der vi angir hovedoppsettet ved å påkalle setContentView
som vist under.
offentlig klasse Main utvider aktivitet / ** Kalt når aktiviteten er først opprettet. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main);
Avhengig av IDE du bruker, må du kanskje legge til noen få importeringserklæringer til Main.java
, filen der din Hoved
klasse liv. De fleste IDE-er vil sette inn disse importerklæringene for deg, men jeg vil sørge for at vi er på samme side før vi fortsetter. Den første importerklæringen, importer android.app.Activity
, importerer Aktivitet
klasse mens den andre importoppgaven, importer android.os.Bundle
, importerer Bunt
klasse. Den tredje importerklæringen, com.example.R
, inneholder definisjonene for ressursene i søknaden. Denne importerklæringen vil avvike fra den du ser nedenfor, da det avhenger av navnet på pakken.
importer android.app.Activity; importere android.os.Bundle; importer com.example.R;
I neste trinn vil vi utnytte SensorEventListener
grensesnitt, som er erklært i Android SDK. For å bruke SensorEventListener
grensesnitt, Hoved
Aktivitetsklassen må implementere den som vist i kodestykket nedenfor. Hvis du ser på den oppdaterte Hoved
aktivitetsklasse, finner du at jeg bruker redskaper
søkeord for å fortelle kompilatoren at Hoved
klassen implementerer SensorEventListener
grensesnitt.
offentlig klasse Hoved utvider Aktivitet implementerer SensorEventListener / ** Kalt når aktiviteten er først opprettet. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main);
For å bruke SensorEventListener
grensesnitt, må du legge til en annen importoppgave som vist nedenfor. De fleste IDE-er vil legge til importoppførelsen for deg, slik at du sannsynligvis ikke trenger å bekymre deg for dette.
importer android.hardware.SensorEventListener;
Fra øyeblikket oppdaterer du Hoved
klasse implementering som vist ovenfor, vil du se noen feil dukker opp. Dette er ikke overraskende siden vi trenger to implementere to nødvendige metoder for SensorEventListener
grensesnitt.
Hvis du bruker IntelliJ IDEA, bør du bli bedt om å legge til disse nødvendige metodene når du klikker på feilen. Hvis du bruker en annen IDE, kan denne oppførselen være annerledes. La oss legge til de to nødvendige metodene for hånd som vist i kodestykket nedenfor. Pass på å legge til disse metodene i Hoved
klasse og utenfor onCreate
metode.
@Override public void onSensorChanged (SensorEvent-hendelse) @Override public void on AccuracyChanged (Sensor sensor, int nøyaktighet)
La oss ta en titt på onSensorChanged
metode. Vi bruker denne metoden for å oppdage shake gestus. De onSensorChanged
Metoden påberopes hver gang den innebygde sensoren oppdager en endring. Denne metoden brukes flere ganger når enheten er i bevegelse. For å bruke Sensor
og SensorEvent
klasser, legger vi til ytterligere to importangivelser som vist nedenfor.
importere android.hardware.Sensor; importer android.hardware.SensorEvent;
Før vi implementerer onSensorChanged
, Vi må deklarere to private variabler i Hoved
klasse, senSensorManager
av type SensorManager
og senAccelerometer
av type Sensor
.
Privat SensorManager SenSensorManager; Privat Sensor SenAccelerometer;
De SensorManager
Klassen er erklært i android.hardware.SensorManager
. Hvis du ser noen feil, dukker opp, dobbeltklikker du at SensorManager
klassen er også importert.
importer android.hardware.SensorManager;
I onCreate
Metode, vi initialiserer variablene vi nettopp har erklært og registrerer en lytter. Ta en titt på den oppdaterte implementeringen av onCreate
metode.
@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 (dette, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
For å initialisere SensorManager
eksempel, påberoper vi oss getSystemService
for å hente systemets SensorManager
eksempel, som vi igjen bruker for å få tilgang til systemets sensorer. De getSystemService
Metoden brukes til å få en referanse til en tjeneste av systemet ved å sende navnet på tjenesten. Med sensorhåndteringen til vår disposisjon, får vi en referanse til systemets akselerometer ved å påkalle getDefaultSensor
på sensorstyreren og passerer typen sensor vi er interessert i. Vi registrerer sensoren ved hjelp av en av SensorManager
s offentlige metoder, registerListener
. Denne metoden aksepterer tre argumenter, aktivitetens kontekst, en sensor og frekvensen der sensorhendelser leveres til oss.
offentlig klasse Hoved utvider Aktivitet implementerer SensorEventListener private SensorManager senSensorManager; Privat Sensor SenAccelerometer; / ** Kalt når aktiviteten er først opprettet. * / @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 (dette, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); @Override public void onSensorChanged (SensorEvent sensorEvent) @Override public void on AccuracyChanged (Sensor sensor, int nøyaktighet)
Det er to andre metoder vi må overstyre, onPause
og onResume
. Dette er metoder for Hoved
klasse. Det er god praksis å avregistrere sensoren når applikasjonen dvale og registrere sensoren igjen når programmet fortsetter. Ta en titt på kodestykket nedenfor for å få en ide om hvordan dette fungerer i praksis.
beskyttet ugyldig onPause () super.onPause (); senSensorManager.unregisterListener (this);
beskyttet ugyldig onResume () super.onResume (); senSensorManager.registerListener (dette, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
Vi kan nå begynne å fokusere på kjøttet i søknaden. Det vil kreve litt matte å finne ut når en rystelsesbevegelse finner sted. Det meste av logikken vil gå inn i onSensorChanged
metode. Vi begynner med å erklære noen få variabler i vår Hoved
klasse. Ta en titt på kodestykket nedenfor.
privat lenge sistUpdate = 0; privat float last_x, last_y, last_z; privat statisk endelig int SHAKE_THRESHOLD = 600;
La oss nå zoome inn på implementeringen av onSensorChanged
metode. Vi tar en referanse til Sensor
eksempel ved bruk av SensorEvent
eksempel som er sendt til oss. Som du kan se i kodestykket under, dobbeltsjekker vi at vi får en referanse til riktig sensortype, systemets akselerometer.
Offentlig tomgang på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; hvis (mySensor.getType () == Sensor.TYPE_ACCELEROMETER)
Det neste trinnet er å trekke ut enhetens posisjon i rommet, x
, y
, og z
akser. Ta en titt på bildet nedenfor for å bedre forstå hva jeg refererer til. De x
akse definerer lateral bevegelse, mens y
akse definerer vertikal bevegelse. De z
akse er litt vanskeligere da den definerer bevegelse inn og ut av flyet definert av x
og y
akser.
For å få verdiene for hver akse, spør vi sensorhendelsen for dens verdier som vist nedenfor. Arrangementet er verdier
Attribut er en rekke flyter.
Offentlig tomgang på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; hvis (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values [0]; float y = sensorEvent.values [1]; float z = sensorEvent.values [2];
Systemets sensorer er utrolig følsomme. Når du holder en enhet i hånden, er den hele tiden i bevegelse, uansett hvor stabil hånden din er. Resultatet er at onSensorChanged
Metoden påberopes flere ganger i sekundet. Vi trenger ikke alle disse dataene, så vi må sørge for at vi bare prøver en delmengde av dataene vi får fra enhetens akselerometer. Vi lagrer systemets nåværende tid (i millisekunder) lagrer den inn CurTime-verdien
og sjekk om mer enn 100
millisekunder har gått siden siste gang onSensorChanged
ble påkalt.
Offentlig tomgang på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; hvis (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values [0]; float y = sensorEvent.values [1]; float z = sensorEvent.values [2]; lang curTime = System.currentTimeMillis (); hvis ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime;
Det siste stykket av puslespillet oppdager om enheten har blitt rystet eller ikke. Vi bruker Matte
klassen for å beregne enhetens hastighet som vist nedenfor. Den statisk erklært SHAKE_THRESHOLD
Variabel brukes til å se om en shake gest er blitt oppdaget eller ikke. modifisering SHAKE_THRESHOLD
øker eller reduserer følsomheten, så vær fri til å spille med verdien.
Offentlig tomgang på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; hvis (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values [0]; float y = sensorEvent.values [1]; float z = sensorEvent.values [2]; lang curTime = System.currentTimeMillis (); hvis ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; flytehastighet = Math.abs (x + y + z - last_x - last_y - siste_z) / diffTime * 10000; hvis (hastighet> SHAKE_THRESHOLD) last_x = x; last_y = y; last_z = z;
Vi har nå et program som kan oppdage en shake gestus ved hjelp av akselerometeret. La oss fullføre dette prosjektet ved å bruke shake gesturen til å velge seks tilfeldige lotteri tall. Jeg skal vise deg hvordan du genererer et tilfeldig tall mellom 1
og 49
, men du er fri til å endre implementeringen for å få det til å fungere med hvordan lotteriet spilles i ditt land.
La oss starte med å sette opp programmets hovedlayoutfil som vi bruker til brukergrensesnittet. Som du ser nedenfor bruker jeg seks rammeoppsett med bakgrunn av et bilde av en ball.
Hver rammeoppsett inneholder en tekstvisning som vil vise et tilfeldig generert lotteri nummer. Merk at hver rammeoppsett og tekstvisning har en id
for å sikre at vi kan referere dem senere.
Med hovedoppsettet klar til bruk, la oss se på nytt Hoved
klasse. Vi begynner med å lage getRandomNumber
, en privat metode for å generere seks tilfeldige tall mellom 1
og 49
.
privat tomt getRandomNumber () ArrayList numbersGenerated = new ArrayList (); for (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 lager først en Arraylist
eksempel, som vi bruker til å lagre de seks tallene i. I hver løkke av til
loop, vi benytter oss av Java Tilfeldig
klassen for å generere et tilfeldig tall. For å sikre at vi får et nummer mellom 1
og 49
, vi legger til 1
til resultatet. Det neste trinnet er å kontrollere om det genererte nummeret allerede er i matelisten, fordi vi bare vil ha unike tall i matelisten.
Vær oppmerksom på at det kan være nødvendig å legge til to importangivelser for å holde kompilatoren glad.
importer java.util.ArrayList; importer java.util.Random;
Det siste trinnet er å vise det tilfeldig genererte nummeret i brukergrensesnittet. Vi får en referanse til tekstvisninger vi opprettet tidligere, og fylle hver tekstvisning med et tilfeldig tall. Vi legger også til en fin animasjon i rammebetingelsene, men vær så snill å unnlate eller endre animasjonen.
privat tomt getRandomNumber () ArrayList numbersGenerated = new ArrayList (); for (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å legge til noen få flere importeringserklæringer for å gjøre alt dette arbeidet. Ta en titt på kodestykket nedenfor.
importer android.view.View; importere android.view.animation.Animation; importer android.view.animation.AnimationUtils; importer android.widget.FrameLayout; importer android.widget.TextView;
Når det gjelder animasjonene, ta en titt på innholdet i animasjonsfilen nedenfor. Legg merke til at du må opprette en anim
mappe i prosjektets ressurs katalog og navn den move_down_ball_first.xml
. Ved å justere verdiene til skala
element, kan du endre animasjonens varighet og posisjonen til hver ball.
Alt som er igjen for oss å gjøre er å ringe getRandomNumber
i onSensorChanged
i Hoved
klasse. Ta en titt på den fullstendige implementeringen av onSensorChanged
Vist under.
Offentlig tomgang på SensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; hvis (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values [0]; float y = sensorEvent.values [1]; float z = sensorEvent.values [2]; lang curTime = System.currentTimeMillis (); hvis ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; flytehastighet = Math.abs (x + y + z - last_x - last_y - siste_z) / diffTime * 10000; hvis (hastighet> SHAKE_THRESHOLD) getRandomNumber (); last_x = x; last_y = y; last_z = z;
I denne opplæringen har jeg vist deg hvordan akselerometeret fungerer, og hvordan du kan bruke det til å oppdage en rystebevegelse. Selvfølgelig er det mange andre brukstilfeller for akselerometeret. Med en grunnleggende forståelse for å oppdage gebyrer ved hjelp av akselerometeret, oppfordrer jeg deg til å eksperimentere med akselerometeret for å se hva annet du kan gjøre med det.
Hvis du jobber med Android-utvikling mye, vil du sannsynligvis løpe over situasjoner der du trenger hjelp med et bestemt aspekt som ikke er spesialitet. I så fall kan du prøve å ansette en av ekspertapputviklerne på Envato Studio for å fullføre arbeidet raskt og pålitelig.