În acest tutorial, vom explora cum să folosim accelerometrul, unul din multele senzori hardware ai smartphone-urilor moderne, într-o aplicație Android. Voi explica ce este un accelerometru și de ce poate fi ceva la care doriți să profitați în aplicațiile Android.
Înainte de apariția zorilor smartphone-uri, una dintre puținele aplicații ale componentelor hardware care puteau interacționa era tastatura. Dar vremurile s-au schimbat și interacțiunea cu componentele hardware devine din ce în ce mai des întâlnită.
Utilizarea gesturilor se simte adesea mai naturală decât interacțiunea cu o interfață de utilizator prin mouse și tastatură. Acest lucru este valabil mai ales pentru dispozitivele touch, cum ar fi smartphone-urile și tabletele. Consider că utilizarea gesturilor poate aduce o aplicație Android la viață, făcând-o mai interesantă și mai interesantă pentru utilizator.
Destul de câteva aplicații utilizează acum accelerometrul. De exemplu, aruncați o privire asupra acestor șabloane de aplicații de pe Envato Market, care includ un joc de curse cu viteză și un agitator de numere aleatorii.
În acest tutorial, vom folosi un gest pe care îl găsiți în numeroase aplicații mobile, gestul de agitare. Vom folosi gestul pentru a genera aleatoriu șase numere de loterie și le vom afișa pe ecran folosind o animație destul de bună.
Începeți un nou proiect Android în IDE-ul preferat (Integrated Development Environment) pentru dezvoltarea Android. Pentru acest tutorial, voi folosi IntelliJ IDEA.
Dacă IDE-ul dvs. suportă dezvoltarea Android, acesta va fi creat un Principal
pentru tine. Numele acestei clase poate varia în funcție de IDE-ul pe care îl utilizați. Principal
clasa joacă un rol cheie atunci când cererea dvs. este lansată. IDE-ul dvs. ar fi trebuit, de asemenea, să fi creat un fișier principal de aspect, care să fie Principal
utilizează clasa pentru a crea interfața de utilizare a aplicației.
Deoarece vom folosi un gest de agitare, este o idee bună să blocați orientarea dispozitivului. Acest lucru va asigura că interfața de utilizare a aplicației nu se schimbă în mod constant între portret și peisaj. Deschideți fișierul manifest al proiectului și setați orientarea ecranului
opțiunea pentru portret
.
Cu proiectul stabilit, este timpul să ne murdărim mâinile și să scriem niște coduri. În prezent, clasa principală de activitate are un onCreate
metoda în care am setat aspectul principal invocând setContentView
așa cum se arată mai jos.
clasa publică Extensie principală Activitate / ** Chemată când activitatea este creată pentru prima dată. * / @Override publică void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main);
În funcție de IDE pe care îl utilizați, este posibil să fie necesar să adăugați câteva declarații de import către Main.java
, fișierul în care dvs. Principal
clasa vieți. Majoritatea IDE-urilor vor introduce aceste declarații de import pentru dvs., dar vreau să fiu sigur că suntem pe aceeași pagină înainte de a continua. Prima declarație de import, importă android.app.Activity
, importă Activitate
clasa în timp ce a doua declarație de import, import șiroid.os.Bundle
, importă Pachet
clasă. A treia declarație de import, com.example.R
, conține definițiile pentru resursele aplicației. Această declarație de import va fi diferită de cea pe care o vedeți mai jos, deoarece depinde de numele pachetului dvs..
importă android.app.Activity; import android.os.Bundle; import com.example.R;
În pasul următor, vom folosi efectul SensorEventListener
, care este declarat în Android SDK. Pentru a utiliza SensorEventListener
interfață, Principal
clasa de activități trebuie să o implementeze așa cum se arată în fragmentul de cod de mai jos. Dacă vă uitați la actualizată Principal
clasa de activitate, veți găsi că folosesc ustensile
cuvânt cheie pentru a spune compilatorului că Principal
clasa implementează SensorEventListener
interfață.
clasa publică principală se extinde Activitatea implementează SensorEventListener / ** Chemată când activitatea este inițial creată. * / @Override publică void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main);
Pentru a utiliza SensorEventListener
trebuie să adăugați o altă declarație de import, după cum se arată mai jos. Majoritatea IDE-urilor vor adăuga inteligent declarația de import pentru dvs., astfel încât, probabil, nu va trebui să vă faceți griji în legătură cu acest lucru.
import android.hardware.SensorEventListener;
Din moment, actualizați Principal
implementarea clasei, așa cum se arată mai sus, veți vedea câteva erori de afișare. Acest lucru nu este surprinzător, deoarece avem nevoie de două implementăm două metode necesare SensorEventListener
interfață.
Dacă utilizați IntelliJ IDEA, ar trebui să vi se solicite să adăugați aceste metode necesare când faceți clic pe eroare. Dacă utilizați un IDE diferit, acest comportament poate fi diferit. Să adăugăm manual cele două metode necesare, așa cum se arată în fragmentul de cod de mai jos. Asigurați-vă că adăugați aceste metode în Principal
clasa și în afara onCreate
metodă.
@Override public void onSensorChanged (eveniment SensorEvent) @Override public void onAccuracyChanged (senzor senzor, precizie int)
Să aruncăm o privire la onSensorChanged
metodă. Vom folosi această metodă pentru a detecta gestul de agitare. onSensorChanged
metoda este invocată de fiecare dată când senzorul încorporat detectează o modificare. Această metodă este invocată în mod repetat de fiecare dată când dispozitivul este în mișcare. Pentru a utiliza Senzor
și SensorEvent
clase, adăugăm două declarații de import suplimentare, după cum se arată mai jos.
import șiroid.hardware.Sensor; import android.hardware.SensorEvent;
Înainte să implementăm onSensorChanged
, trebuie să declarăm două variabile private în Principal
clasă, senSensorManager
de tip SensorManager
și senAccelerometer
de tip Senzor
.
privat SensorManager senSensorManager; senzor privat senAccelerometer;
SensorManager
clasa este declarată în android.hardware.SensorManager
. Dacă vedeți erori de afișare, verificați din nou că SensorManager
este importată și clasa.
import șiroid.hardware.SensorManager;
În onCreate
, inițializăm variabilele pe care tocmai le-am declarat și le înregistrăm pe un ascultător. Aruncați o privire la implementarea actualizată a onCreate
metodă.
@Override protejate void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); senSensorManager = (senzorManager) getSystemService (Context.SENSOR_SERVICE); senAccelerometru = senSensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER); senSensorManager.registerListener (acest, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
Pentru a inițializa SensorManager
exemplu, invocăm getSystemService
pentru a prelua sistemul SensorManager
exemplu, pe care noi, la rândul nostru, le folosim pentru a accesa senzorii sistemului. getSystemService
metoda este folosită pentru a obține o referință la un serviciu al sistemului prin trecerea numelui serviciului. Cu managerul de senzori la dispoziția noastră, vom primi o referință la accelerometrul sistemului invocând getDefaultSensor
pe managerul de senzori și trecând de la tipul de senzor de care suntem interesați. Apoi, înregistram senzorul utilizând unul din SensorManager
metodele publice, registerListener
. Această metodă acceptă trei argumente, contextul activității, un senzor și rata la care sunt livrate evenimentele senzorilor.
clasa publică principală se extinde Activitatea implementează SensorEventListener private SensorManager senSensorManager; senzor privat senAccelerometer; / ** Chemată când se creează prima activitate. * / @Override publică void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); senSensorManager = (senzorManager) getSystemService (Context.SENSOR_SERVICE); senAccelerometru = senSensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER); senSensorManager.registerListener (acest, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); @Override public void onSensorChanged (SensorEvent sensorEvent) @Overide public void onAccuracyChanged (senzor senzor, precizie int)
Există două alte metode pe care trebuie să le suprimăm, onPause
și onResume
. Acestea sunt metode ale Principal
clasă. Este o practică bună să anulați înregistrarea senzorului atunci când aplicația hibernează și să înregistreze senzorul din nou când aplicația se reia. Uitați-vă la fragmentele de cod de mai jos pentru a obține o idee despre cum funcționează acest lucru în practică.
protejat void onPause () super.onPause (); senSensorManager.unregisterListener (aceasta);
protejat void onResume () super.onResume (); senSensorManager.registerListener (acest, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
Acum putem începe să ne concentrăm asupra cărnii cererii. Va fi nevoie de un pic de matematică pentru a descoperi când are loc un gest de agitare. Cea mai mare parte a logicii va intra în onSensorChanged
metodă. Începem prin a declara câteva variabile în cadrul nostru Principal
clasă. Uitați-vă la fragmentul de cod de mai jos.
private long lastUpdate = 0; float privat last_x, last_y, last_z; finale statice private int int SHAKE_THRESHOLD = 600;
Acum, măriți performanța aplicației onSensorChanged
metodă. Luăm o referință la Senzor
instanță folosind SensorEvent
instanță care ne este transmisă. După cum puteți vedea în fragmentul de cod de mai jos, verificăm din nou că avem o referință la tipul de senzor corect, accelerometrul sistemului.
public void onSensorChange (SensorEvent senzorEvent) Sensor mySensor = sensorEvent.sensor; dacă (mySensor.getType () == Sensor.TYPE_ACCELEROMETER)
Următorul pas este extragerea poziției dispozitivului în spațiu X
, y
, și z
axă. Uitați-vă la imaginea de mai jos pentru a înțelege mai bine ce mă refer. X
axa definește mișcarea laterală, în timp ce y
axa definește mișcarea verticală. z
axa este puțin mai complicată deoarece definește mișcarea în și din planul definit de X
și y
axă.
Pentru a obține valorile fiecărei axe, cerem evenimentul senzorului pentru valorile sale, după cum se arată mai jos. Evenimentele valorile
atributul este o serie de flotoare.
public void onSensorChange (SensorEvent senzorEvent) Sensor mySensor = sensorEvent.sensor; dacă (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = senzorEvent.value [0]; flotat y = senzorEvaluarea valorilor [1]; float z = senzorEvaluarea valorilor [2];
Senzorii sistemului sunt incredibil de sensibili. Când țineți un dispozitiv în mână, acesta este în mișcare constantă, indiferent cât de stabilă este mâna. Rezultatul este că onSensorChanged
metoda este invocată de mai multe ori pe secundă. Nu avem nevoie de toate aceste date, așa că trebuie să ne asigurăm că eșantionăm doar un subset de date pe care le obținem de la accelerometrul dispozitivului. Stocam ora actuala a sistemului (in milisecunde) curTime
și verificați dacă mai mult de 100
milisecunde au trecut de la ultima dată onSensorChanged
a fost invocată.
public void onSensorChange (SensorEvent senzorEvent) Sensor mySensor = sensorEvent.sensor; dacă (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = senzorEvent.value [0]; flotat y = senzorEvaluarea valorilor [1]; float z = senzorEvaluarea valorilor [2]; curTime lung = System.currentTimeMillis (); dacă ((curTime - lastUpdate)> 100) lung diffTime = (curTime - lastUpdate); lastUpdate = curTime;
Ultima piesă a puzzle-ului detectează dacă dispozitivul a fost scuturat sau nu. Noi folosim Math
pentru a calcula viteza dispozitivului, după cum se arată mai jos. Declarat static SHAKE_THRESHOLD
variabila este utilizată pentru a vedea dacă a fost detectat sau nu un gest de agitare. modificarea SHAKE_THRESHOLD
crește sau scade sensibilitatea, deci nu ezitați să jucați cu valoarea sa.
public void onSensorChange (SensorEvent senzorEvent) Sensor mySensor = sensorEvent.sensor; dacă (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = senzorEvent.value [0]; flotat y = senzorEvaluarea valorilor [1]; float z = senzorEvaluarea valorilor [2]; curTime lung = System.currentTimeMillis (); dacă ((curTime - lastUpdate)> 100) lung diffTime = (curTime - lastUpdate); lastUpdate = curTime; viteza flotorului = Math.abs (x + y + z - ultima_x - ultima_y - ultima_z) / diffTime * 10000; dacă (viteza> SHAKE_THRESHOLD) last_x = x; last_y = y; last_z = z;
Acum avem o aplicație care poate detecta un gest de agitare folosind accelerometrul. Să terminăm acest proiect folosind gestul pentru a alege șase numere loterie aleatorii. Vă voi arăta cum să generați un număr aleator între 1
și 49
, dar sunteți liber să modificați implementarea mea pentru ca aceasta să funcționeze cu modul în care este jucată loteria în țara dvs..
Să începem prin configurarea fișierului de aspect principal al aplicației pe care îl vom folosi pentru interfața cu utilizatorul. După cum puteți vedea mai jos, folosesc șase layout-uri de cadre cu fundal de imagine a unei mingi.
Fiecare aspect al cadrului conține o vizualizare text care va afișa un număr loterie generat la întâmplare. Rețineți că fiecare aspect de cadru și vizualizare de text are un id
pentru a vă asigura că le putem trimite mai târziu.
Cu aspectul principal gata de utilizare, să revizuim Principal
clasă. Începem prin a crea getRandomNumber
, o metodă privată pentru generarea a șase numere aleatorii între 1
și 49
.
privat void getRandomNumber () ArrayList numereGenerat = nou ArrayList (); pentru (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--;
Mai întâi creăm un ArrayList
exemplu, pe care îl folosim pentru a stoca cele șase numere. În fiecare buclă din pentru
bucla, vom profita de Java Întâmplător
pentru a genera un număr aleator. Pentru a vă asigura că avem un număr între 1
și 49
, adaugam 1
la rezultat. Următorul pas este să verificați dacă numărul generat este deja în lista de matrice, deoarece dorim numai numere unice în lista de matrice.
Rețineți că poate fi necesar să adăugați încă două declarații de import pentru a menține compilatorul fericit.
import java.util.ArrayList; import java.util.Random;
Ultimul pas este afișarea numărului generat aleator în interfața cu utilizatorul. Obținem o referință la vederile de text pe care le-am creat mai devreme și vom popula fiecare vizualizare text cu un număr aleatoriu. Adăugăm, de asemenea, o animație elegantă în layout-urile de cadre, dar nu ezitați să omiteți sau să modificați animația.
privat void getRandomNumber () ArrayList numereGenerat = nou ArrayList (); pentru (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);
Va trebui să adăugăm câteva declarații de import suplimentare pentru a face toate aceste lucruri. Uitați-vă la fragmentul de cod de mai jos.
import șiroid.view.View; import șiroid.view.animation.Animation; import șiroid.view.animation.AnimationUtils; importă android.widget.FrameLayout; import șiroid.widget.TextView;
În ceea ce privește animațiile, aruncați o privire la conținutul fișierului de animație de mai jos. Rețineți că trebuie să creați un anim
folder în directorul de resurse al proiectului și numiți-l move_down_ball_first.xml
. Prin ajustarea valorilor scară
element, puteți modifica durata animației și poziția fiecărei mingi.
Tot ce a mai rămas pentru noi este să sunăm getRandomNumber
în onSensorChanged
în Principal
clasă. Aruncați o privire la implementarea completă a onSensorChanged
prezentat mai jos.
public void onSensorChange (SensorEvent senzorEvent) Sensor mySensor = sensorEvent.sensor; dacă (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = senzorEvent.value [0]; flotat y = senzorEvaluarea valorilor [1]; float z = senzorEvaluarea valorilor [2]; curTime lung = System.currentTimeMillis (); dacă ((curTime - lastUpdate)> 100) lung diffTime = (curTime - lastUpdate); lastUpdate = curTime; viteza flotorului = Math.abs (x + y + z - ultima_x - ultima_y - ultima_z) / diffTime * 10000; dacă (viteza> SHAKE_THRESHOLD) getRandomNumber (); last_x = x; last_y = y; last_z = z;
În acest tutorial, v-am arătat cum funcționează accelerometrul și cum îl puteți folosi pentru a detecta un gest de agitare. Desigur, există multe alte cazuri de utilizare pentru accelerometru. Cu o înțelegere de bază a detectării gesturilor utilizând accelerometrul, vă încurajez să experimentați cu accelerometrul pentru a vedea ce altceva puteți face cu acesta.
Dacă lucrați foarte mult cu dezvoltarea Android, probabil că veți întâlni situații în care aveți nevoie de ajutor pentru un anumit aspect care nu este specialitatea dvs. În acest caz, încercați să angajați unul dintre dezvoltatorii de aplicații de la Envato Studio pentru a finaliza lucrarea rapid și fiabil.