Smartphone-urile sunt pline de senzori hardware, cum ar fi accelerometre, senzori de lumină, giroscoape și așa mai departe. Aflați cum puteți aduna date de la acești senzori prin implementarea unui înregistrator barometric.
Într-o continuare a ultimului tutorial, Picking App Components, de data aceasta vom implementa regulat codul pentru citirea datelor senzorilor barometrici. Veți învăța să citiți datele senzorului și cum să programați evenimente recurente, astfel încât aplicația și serviciile sale să nu mai rămână în desfășurare.
Acest tutorial presupune că aveți o înțelegere de bază despre Android și Java, că aveți toate instrumentele Android instalate și care funcționează și că vă simțiți confortabil cu încărcarea și testarea aplicațiilor pe un dispozitiv Android. Vom folosi senzorul hardware barometru în această aplicație. Dacă nu aveți un dispozitiv cu acest senzor, puteți înlocui un alt senzor similar în scopuri de testare, dar rezultatele sau utilitatea nu pot fi echivalente.
Senzorii hardware sunt accesați prin intermediul clasei SensorManager. Printr-o instanță a acestei clase, o aplicație poate interoga diferite obiecte senzor care reprezintă hardware-ul subiacent. Folosind acestea, o aplicație poate începe să asculte date provenite de la hardware-ul senzorului.
Mai întâi, obțineți o instanță a clasei SensorManager, după cum urmează:
SenzorManager sensorManager = (SensorManager) getSystemService (SENSOR_SERVICE);
Apoi, interogarea senzorului Sensor.TYPE_PRESSURE, care este senzorul barometric:
Senzor senzor = sensorManager.getDefaultSensor (Sensor.TYPE_PRESSURE);
Utilizarea senzorului de clasă SensorManager și a cititorului nu necesită nicio permisiune specială.
Acum vă puteți înregistra pentru a primi evenimente de la senzor. Pentru a face acest lucru, trebuie să implementați un SensorEventListener și să spuneți clasei SensorManager despre acest lucru.
De exemplu, iată structura pentru implementarea unui SensorEventListener:
class MyListener implementează SensorEventListener @Override public void onAccuracyChanged (senzor senzor, precizie int) // TODO @Override public void onSensorChanged (eveniment SensorEvent) // TODO
Apoi, înregistrați-vă pentru evenimente prin a spune SensorManager despre ascultător:
sensorManager.registerListener (myListenerInstance, senzor, SensorManager.SENSOR_DELAY_NORMAL);
Vă puteți înregistra pentru a primi actualizări de evenimente la diferite tarife. Cu cât este mai rapidă rata, cu atât mai frecvente sunt actualizările, dar și cu cât mai rapid va fi descărcată bateria dispozitivului. Aici folosim rata implicită. Verificați valoarea returnată a apelului registerListener () pentru a vedea dacă a avut succes sau nu. Dacă este adevărat, senzorul este disponibil și ascultarea a început. Dacă este fals, senzorul poate să nu fie disponibil (din orice motiv).
Clasa care recepționează evenimentele senzorilor este generică pentru toți senzorii prin intermediul clasei SensorEvent. Ca atare, câmpul pentru valoarea SensorEvent este un tablou care gestionează mai multe date decât un senzor barometric numeric unic. Suntem interesați doar de prima valoare a matricei și a timestampului:
@Override public void onSensorChanged (eveniment SensorEvent) timestamp lung = event.timestamp; valoarea float = event.values [0]; // face ceva cu valorile
În cele din urmă, pentru a nu mai asculta senzorul, pur și simplu o anulați:
sensorManager.unregisterListener (myListenerInstance);
Trebuie să vă înregistrați numai când aplicația dvs. este pregătită și are nevoie de datele senzorului și apoi să vă deselectați de îndată ce nu mai este necesară. Acest lucru ajută la utilizarea cu înțelepciune a resurselor dispozitivelor, precum bateria.
Probabil nu sunteți interesat să lăsați aplicația să ruleze tot timpul pentru a verifica valorile senzorilor. În schimb, creați un serviciu și lansați serviciul în mod regulat, utilizând o alarmă repetată prin intermediul sistemului AlarmManager.
Un serviciu pe Android este o modalitate de a rula codul de aplicație care nu este legat de o anumită activitate și nu are nevoie de un UI propriu. Ca o activitate, codul dintr-un serviciu rulează pe firul principal, astfel încât tehnicile de prelucrare a fundalului obișnuit trebuie efectuate pentru operațiuni de lungă durată. Un serviciu poate fi folosit fie printr-un Intent, fie prin legare și efectuând apeluri de la distanță. Tipul de serviciu pe care îl implementăm este cel mai bine realizat prin manipularea intenției.
Miezul unei clase de servicii are două metode de implementare, metoda onStartCommand () și metoda onBind (). Din moment ce nu ne ocupăm de legare, vom proceda pur și simplu cu Bind (). Iată nucleul Serviciului nostru, inclusiv implementarea SensorEventListener:
clasa publică BaroLoggerService se extinde Serviciul implementează SensorEventListener String final static privat DEBUG_TAG = "BaroLoggerService"; privat sensorManager sensorManager = null; senzor senzor privat = nul; @Override public int peStartCommand (Intent intent, int flags, int startId) sensorManager = (SensorManager) getSystemService (SENSOR_SERVICE); senzor = sensorManager.getDefaultSensor (Sensor.TYPE_PRESSURE); sensorManager.registerListener (acest senzor, SensorManager.SENSOR_DELAY_NORMAL); întoarceți START_STICKY; @Override publice IBinder onBind (intenția intenției) return null; @Override public void onAccuracyChanged (senzor senzor, precizie int) // nu face nimic @Override public void onSensorChanged (eveniment SensorEvent) // apuca valorile și timestamp // ... // opri senzorul și service sensorManager.unregisterListener ( acest); stopSelf ();
Scrierea datelor pe disc este o operație de blocare și ar trebui efectuată pe un fir de fundal. O modalitate simplă de a face acest lucru este printr-un AsyncTask. În cadrul Serviciului, putem adăuga un AsyncTask și îl vom transmite SensorEvent pentru manipulare, cum ar fi:
@Override public void onSensorChanged (eveniment SensorEvent) / apuca valorile și timestamp - de pe firul principal nou SensorEventLoggerTask () execute (eveniment); // opriți oprirea serviciuluiSelf (); private class SensorEventLoggerTask extinde AsyncTask@Override protejat Void doInBackground (evenimente SensorEvent ...) eveniment SensorEvent = evenimente [0]; // log valoarea
Un serviciu este inițiat în mod normal prin metoda StartService (). De exemplu, următoarele ar funcționa dintr-o clasă de activitate:
Intent intent = intenție nouă (getApplicationContext (), BaroLoggerService.class); startService (intenție);
Aceasta nu este ceea ce dorim totuși. Vrem ca serviciul să ruleze doar ocazional, chiar dacă aplicația nu funcționează și chiar dacă aparatul este adormit. Clasa AlarmManager ne permite să facem acest lucru.
Clasa AlarmManager vă permite să programați evenimentele într-o manieră recurentă. Permite chiar și programarea eficientă a numeroaselor evenimente diferite, nu numai ale dvs., ceea ce reprezintă o modalitate bună de reducere a utilizării bateriei.
Iată codul pe care îl puteți plasa într-o Activitate sub un handler de buzuri, de exemplu, pentru a activa Serviciul pentru a repeta o dată pe oră:
Planificatorul alarmManager = (AlarmManager) getSystemService (Context.ALARM_SERVICE); Intent intent = intenție nouă (getApplicationContext (), BaroLoggerService.class); PendingIntent scheduledIntent = PendingIntent.getService (getApplicationContext (), 0, intenție, PendingIntent.FLAG_UPDATE_CURRENT); scheduler.setInexactRepeating (AlarmManager.RTC_WAKEUP, System.currentTimeMillis (), AlarmManager.INTERVAL_HOUR, programatIntent);
Utilizăm metoda setInexactRepeating () cu un interval specific definit, INTERVAL_HOUR, pentru a profita de sistemul care se trezește pentru mai mult decât munca noastră. În plus, folosim opțiunea RTC_WAKEUP pentru a indica faptul că vrem ca dispozitivul să fie trezit pentru această alarmă, în loc să aștepte până când se trezește din alt motiv.
De asemenea, pentru scopuri de testare, am folosit un interval de un minut, astfel încât nu a trebuit să așteptăm câteva ore pentru a colecta mai multe puncte de date.
Opriți alarma printr-un apel la metoda cancel () utilizând aceeași intenție:
Planificatorul alarmManager = (AlarmManager) getSystemService (Context.ALARM_SERVICE); Intenția intenției = intenția nouă (acest lucru, BaroLoggerService.class); PendingIntent scheduledIntent = PendingIntent.getService (getApplicationContext (), 0, intenție, PendingIntent.FLAG_UPDATE_CURRENT); scheduler.cancel (scheduledIntent);
Puteți efectua aceste apeluri în orice fel doriți. Am creat câteva controale ale butoanelor care au apelat la metode în activitatea noastră cu aceste apeluri.
În acest tutorial, ați învățat să verificați periodic o valoare a senzorului în fundal utilizând obiectele SensorManager, Service și AlarmManager. Seria va continua cu mai multe informații despre stocarea și afișarea datelor.
Ca provocare, implementați acest cod pe cont propriu. Încercați alte tipuri de senzori pe care dispozitivul dvs. le acceptă. Acceptă TYPE_AMBIENT_TEMPERATURE? TYPE_RELATIVE_HUMIDITY? TYPE_LIGHT? Ar fi util să înregistrați locația măsurătorilor? Fiți creativi și spuneți-ne ce vă aduceți în comentarii!
Dezvoltatorii mobili Lauren Darcey și Shane Conder au coautorizat mai multe cărți despre dezvoltarea Android: o carte de programare în profunzime intitulată Dezvoltarea aplicațiilor fără fir Android (acum în ediția a treia ca set de două volume) și Sams Învățați-vă dezvoltarea de aplicații Android în 24 de ore. Când nu scriu, își petrec timpul dezvoltând software-ul mobil la compania lor și oferind servicii de consultanță. Acestea pot fi obținute prin e-mail la androidwirelessdev@[email protected], prin intermediul blogului lor la androidbook.blogspot.com, și pe Twitter @ androidwireless.