Sensors API — este interfața platformei Android pentru accesarea senzorilor hardware ai dispozitivului. API oferă o modalitate unică de obținere a datelor de la accelerometru, giroscop, magnetometru, senzor de lumină și alți senzori. Conform datelor Google, 2026, peste 95% din dispozitivele Android moderne sunt echipate cu cel puțin trei tipuri de senzori, ceea ce deschide oportunități largi pentru dezvoltarea aplicațiilor context-sensitive.
Puncte cheie
Sensors API — este interfața de programare a Android Framework, care oferă dezvoltatorilor acces la senzorii hardware ai dispozitivului mobil. API face parte din Android SDK începând cu versiunea 1.0 și este accesibil prin pachetul android.hardware. Interfața abstractizează diferențele dintre implementările senzorilor de la diferiți producători — Qualcomm, MediaTek, Samsung Exynos — și oferă un model unic de lucru cu senzorii.
API permite efectuarea a trei operații cheie: obținerea listei senzorilor disponibili, înregistrarea ascultătorilor pentru primirea datelor și gestionarea frecvenței de actualizare a citirilor. SensorManager este punctul central de acces la toate operațiile. Sistemul notifică aplicația prin callback-ul onSensorChanged, transmițând un obiect SensorEvent cu un tablou de valori float.
Pe durata existenței Android, API a trecut prin mai multe etape de dezvoltare. În versiunea 2.3 (Gingerbread) a apărut suportul pentru Batch Processing — gruparea evenimentelor senzorului pentru reducerea consumului de energie. Android 4.0 (Ice Cream Sandwich) a adăugat senzorii virtuali Gravity și Linear Acceleration. Începând cu Android 8.0, sistemul a limitat accesul în fundal la senzori pentru creșterea confidențialității.
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensorList: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)
sensorList.forEach { sensor ->
Log.d("Senzori", "${sensor.name} — ${sensor.type}")
}
Nu toate dispozitivele au același set de senzori. Aplicația trebuie să verifice disponibilitatea unui senzor specific înainte de înregistrarea ascultătorului. Emulatorul Android suportă doar un set limitat de senzori — accelerometru și magnetometru. Pentru testarea celorlalți senzori este necesar un dispozitiv fizic. Începând cu Android 12, aplicațiile trebuie să declare utilizarea senzorilor în manifest.
Android clasifică toți senzorii în trei categorii: Motion (mișcare), Position (poziție) și Environment (mediu). Senzorii Motion includ accelerometrul, giroscopul și pedometrul. Senzorii Position includ magnetometrul și Orientation. Environment — senzorul de lumină, presiune, temperatură și umiditate.
| Categorie | Senzori | Tip (constantă) | Fizic/Virtual |
|---|---|---|---|
| Motion | Accelerometru | TYPE_ACCELEROMETER | Fizic |
| Motion | Giroscop | TYPE_GYROSCOPE | Fizic |
| Motion | Pedometru | TYPE_STEP_COUNTER | Fizic |
| Motion | Gravity | TYPE_GRAVITY | Virtual |
| Position | Magnetometru | TYPE_MAGNETIC_FIELD | Fizic |
| Position | Rotation Vector | TYPE_ROTATION_VECTOR | Virtual |
| Environment | Lumină | TYPE_LIGHT | Fizic |
| Environment | Presiune | TYPE_PRESSURE | Fizic |
Accelerometrul măsoară accelerația în m/s² pe trei axe — X, Y și Z. Valorile includ gravitația (9.8 m/s² pe axa Z în stare de repaus). Giroscopul măsoară viteza unghiulară în rad/s — viteza de rotație a dispozitivului în jurul fiecărei axe. Combinația acestor doi senzori este utilizată în navigație, jocuri și aplicații AR.
class SensorActivity : Activity(), SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
textView.text = "X: $x, Y: $y, Z: $z"
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}
Magnetometrul (TYPE_MAGNETIC_FIELD) măsoară câmpul magnetic în microtesla (µT) pe trei axe. Este folosit ca busolă digitală — în combinație cu accelerometrul permite determinarea azimutului dispozitivului. Rotation Vector — senzor virtual care combină datele de la giroscop, accelerometru și magnetometru pentru determinarea precisă a orientării.
Senzorul de lumină (TYPE_LIGHT) măsoară nivelul de iluminare externă în lucși (lx). Este utilizat pentru reglarea automată a luminozității ecranului. Senzorul de presiune (TYPE_PRESSURE) măsoară presiunea atmosferică în hectopascali (hPa) — folosit în aplicații de navigație pentru determinarea altitudinii deasupra nivelului mării.
Sensors API este construit pe o arhitectură client-server. Aplicația este clientul, SensorManager — serviciul de sistem Android. Când aplicația înregistrează un ascultător prin registerListener, SensorManager se conectează la HAL (Hardware Abstraction Layer) — driverul de nivel jos al senzorului care funcționează la nivelul nucleului Linux.
Driverul HAL primește datele brute de la cipul hardware, filtrează zgomotul și le trimite în sus pe stivă — prin SensorService (proces de sistem) către aplicație. Datele sunt transmise sub formă de obiect SensorEvent, care conține un tablou de valori float values și un marcaj temporal în nanosecunde. Frecvența evenimentelor depinde de modul de livrare selectat.
La înregistrarea ascultătorului, dezvoltatorul specifică întârzierea dorită între evenimente prin constantele SENSOR_DELAY_NORMAL (200 ms), SENSOR_DELAY_UI (60 ms), SENSOR_DELAY_GAME (20 ms) și SENSOR_DELAY_FASTEST (0 ms — frecvență maximă). Frecvența reală poate diferi — sistemul optimizează consumul de energie.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.registerListener(
this,
sensor,
SensorManager.SENSOR_DELAY_GAME
)
Începând cu Android 2.3, senzorii suportă modul lot — evenimentele se acumulează într-un buffer FIFO și sunt livrate într-un singur pachet. Acest lucru permite procesorului să rămână mai mult timp în modul de repaus, reducând consumul de energie cu până la 60%. Dimensiunea buffer-ului depinde de cipul senzorului și este specificată în câmpul Sensor.fifoMaxEventCount.
SensorManager — serviciu de sistem accesibil prin getSystemService(Context.SENSOR_SERVICE). Oferă metode pentru obținerea listei de senzori, obținerea unui senzor implicit specific și înregistrarea/ anularea ascultătorilor. SensorManager — singleton, o singură instanță pentru întreaga aplicație.
Înainte de utilizarea senzorului, trebuie verificată existența acestuia. Metoda getDefaultSensor(type) returnează null dacă senzorul nu este disponibil pe dispozitiv. Obținerea null fără verificare va duce la NullPointerException la înregistrarea ascultătorului. Lista tuturor senzorilor este returnată de metoda getSensorList(type).
fun checkSensorAvailability(type: Int): Boolean {
val sensorManager =
getSystemService(Context.SENSOR_SERVICE) as SensorManager
return sensorManager.getDefaultSensor(type) != null
}
// Utilizare:
if (checkSensorAvailability(Sensor.TYPE_GYROSCOPE)) {
Log.d("Sensor", "Giroscop disponibil")
}
Ascultătorul se înregistrează prin registerListener(listener, sensor, delay). Important: anularea ascultătorului trebuie făcută în metoda onPause() prin unregisterListener(listener). Dacă nu se face acest lucru, aplicația va continua să primească evenimente ale senzorului, descărcând bateria chiar și în fundal. Android 8+ afișează un avertisment în logcat despre ascultătorii neînregistrați.
Metoda onAccuracyChanged(sensor, accuracy) este apelată la modificarea preciziei senzorului. Valorile: SENSOR_STATUS_ACCURACY_HIGH, MEDIUM, LOW și UNRELIABLE. La primirea UNRELIABLE, datele senzorului trebuie ignorate până la restabilirea preciziei. De exemplu, magnetometrul necesită calibrare — agitarea dispozitivului în formă de opt.
Să examinăm exemple practice de utilizare a Sensors API în aplicații Android cu Kotlin. Primul exemplu — determinarea orientării ecranului cu accelerometrul. Al doilea — citirea indicațiilor magnetometrului cu calibrare. Al treilea — detector de pași cu pedometru.
Pentru determinarea orientării se folosește combinația dintre accelerometru și magnetometru. Metoda SensorManager.getRotationMatrix() calculează matricea de rotație, iar getOrientation() extrage unghiurile pitch, roll și azimuth. Azimuth (azimut) — unghiul față de nordul magnetic în radiani.
val gravity = FloatArray(3)
val geomagnetic = FloatArray(3)
val rotationMatrix = FloatArray(9)
val orientation = FloatArray(3)
SensorManager.getRotationMatrix(
rotationMatrix, null, gravity, geomagnetic
)
SensorManager.getOrientation(rotationMatrix, orientation)
// orientation[0] — azimuth, [1] — pitch, [2] — roll
val azimuthDeg = Math.toDegrees(orientation[0].toDouble())
Pedometrul (TYPE_STEP_COUNTER) returnează numărul total de pași efectuați de utilizator de la ultima repornire a dispozitivului. Senzorul funcționează la nivel hardware — este activ chiar și când aplicația nu rulează. Pentru a obține numărul de pași pe sesiune, trebuie salvată valoarea inițială și calculată diferența.
var initialSteps = 0
var isInitialized = false
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_STEP_COUNTER) {
if (!isInitialized) {
initialSteps = event.values[0].toInt()
isInitialized = true
}
val currentSteps = event.values[0].toInt()
val sessionSteps = currentSteps - initialSteps
Log.d("Pași", "Pași în sesiune: $sessionSteps")
}
}
Senzorul de lumină permite adaptarea interfeței la condițiile de mediu. La iluminare scăzută (sub 10 lx) se poate trece la tema întunecată. La lumină solară puternică (peste 10000 lx) — se poate crește contrastul. Pentru filtrarea zgomotului se folosește media mobilă a ultimelor 5 valori.
Android oferă mai mulți senzori virtuali care nu au un echivalent hardware direct. Senzorul virtual își calculează indicațiile pe baza combinației senzorilor fizici. Aceasta reduce sarcina dezvoltatorului — sistemul însuși implementează algoritmii de fuziune a datelor.
Senzorul Gravity (TYPE_GRAVITY) extrage componenta gravitațională din citirile accelerometrului cu ajutorul unui filtru low-pass. Linear Acceleration (TYPE_LINEAR_ACCELERATION) — invers, elimină gravitația și lasă doar accelerația liniară a dispozitivului. Suma dintre Gravity și Linear Acceleration oferă citirile brute ale accelerometrului.
Rotation Vector — cel mai complex senzor virtual. Combină datele de la giroscop (modificări de înaltă frecvență), accelerometru (vectorul gravitației) și magnetometru (orientarea față de nord). Rezultatul — un cuaternion care descrie orientarea absolută a dispozitivului în spațiu. Folosit în aplicații AR și căști VR.
Game Rotation Vector — o versiune simplificată a Rotation Vector fără utilizarea magnetometrului. Aceasta oferă o precizie mai scăzută a determinării azimutului, dar o frecvență de actualizare mai mare și stabilitate. Recomandat pentru jocuri unde latența redusă este importantă, nu orientarea absolută față de nord.
Senzorii — una dintre cele mai consumatoare de energie componente ale dispozitivului. Accelerometrul și giroscopul la frecvența maximă de interogare pot descărca bateria în 3–4 ore de funcționare continuă. Optimizarea lucrului cu senzorii este o sarcină critică pentru orice aplicație care utilizează Sensors API.
Nu utiliza SENSOR_DELAY_FASTEST fără necesitate. Pentru animații UI este suficient SENSOR_DELAY_UI (60 ms). Pentru determinarea orientării ecranului — SENSOR_DELAY_NORMAL (200 ms). Cu cât frecvența este mai mare, cu atât procesorul petrece mai mult timp în stare activă. Diferența dintre NORMAL și FASTEST este de până la 10x în consumul de energie.
Începând cu Android 8.0 (API 26), aplicațiile în fundal primesc evenimente ale senzorilor cu frecvență redusă. În Android 12+ accesul în fundal la senzorii Motion și Position necesită permisiunea BODY_SENSORS_BACKGROUND. Anulează înregistrarea ascultătorului la trecerea aplicației în modul fundal — aceasta prelungește durata de viață a bateriei.
Folosește procesarea în lot prin metoda registerListener(listener, sensor, delay, maxReportLatencyUs). Parametrul maxReportLatencyUs specifică întârzierea maximă de livrare a evenimentelor în microsecunde. La valoarea 1000000 (1 secundă), evenimentele se acumulează în buffer-ul FIFO al senzorului și sunt livrate o dată pe secundă — procesorul iese mai rar din starea de repaus.
Întrebări frecvente
Setul minim — accelerometru și magnetometru. Acești doi senzori sunt prezenți pe peste 95% din dispozitive. Giroscopul, senzorul de lumină și senzorul de proximitate — pe 70–80% din modelele moderne. Ceilalți senzori (presiune, temperatură, umiditate, pedometru) sunt mai puțin întâlniți și depind de categoria de preț a dispozitivului.
TYPE_ACCELEROMETER returnează accelerația completă, inclusiv gravitația (9.8 m/s²). TYPE_LINEAR_ACCELERATION returnează accelerația fără gravitație — doar accelerația de la mișcarea dispozitivului. Dacă dispozitivul este nemișcat, accelerometrul va arăta 9.8 m/s² pe axa Z, iar Linear Acceleration — 0 pe toate axele.
Folosește getPackageManager().hasSystemFeature() cu constantele corespunzătoare: FEATURE_SENSOR_ACCELEROMETER, FEATURE_SENSOR_GYROSCOPE, FEATURE_SENSOR_PROXIMITY și altele. Metoda alternativă — apelează getDefaultSensor(type) și verifică rezultatul pentru null. Prima metodă este preferată pentru verificare în faza de inițializare.
Datele brute de la senzori conțin zgomot. Pentru netezire folosește un filtru low-pass: newValue = alpha * rawValue + (1 — alpha) * previousValue. Coeficientul alpha = 0.1–0.3 oferă un echilibru bun între receptivitate și netezime. Pentru giroscop se aplică și un filtru high-pass pentru eliminarea derivei de zero.
Da, dar cu limitări. Începând cu Android 8.0, frecvența evenimentelor senzorului este redusă pentru aplicațiile în fundal. Începând cu Android 12, este necesară permisiunea BODY_SENSORS_BACKGROUND pentru accesul la senzori în fundal. Pentru lucrul în fundal se recomandă utilizarea unui Foreground Service cu notificare.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și