Sensors API è un'interfaccia della piattaforma Android per accedere ai sensori hardware del dispositivo. L'API fornisce un modo unificato per ottenere dati dall'accelerometro, giroscopio, magnetometro, sensore di luce e altri sensori. Secondo Google, 2026, oltre il 95% dei dispositivi Android moderni è dotato di almeno tre tipi di sensori, aprendo ampie possibilità per lo sviluppo di applicazioni context-aware.
Punti chiave
Sensors API è un'interfaccia software del framework Android che fornisce agli sviluppatori l'accesso ai sensori hardware del dispositivo mobile. L'API fa parte dell'Android SDK dalla versione 1.0 ed è disponibile tramite il pacchetto android.hardware. L'interfaccia astrae le differenze tra le implementazioni dei sensori di diversi produttori — Qualcomm, MediaTek, Samsung Exynos — e fornisce un modello unificato per lavorare con i sensori.
L'API consente tre operazioni chiave: ottenere un elenco dei sensori disponibili, registrare listener per ricevere dati e gestire la frequenza di aggiornamento. SensorManager funge da punto di accesso centrale per tutte le operazioni. Il sistema notifica l'applicazione tramite il callback onSensorChanged, passando un oggetto SensorEvent con un array di valori float.
Nel corso dell'esistenza di Android, l'API ha attraversato diverse fasi di sviluppo. La versione 2.3 (Gingerbread) ha introdotto il supporto per l'elaborazione batch — raggruppamento degli eventi del sensore per ridurre il consumo energetico. Android 4.0 (Ice Cream Sandwich) ha aggiunto i sensori virtuali Gravity e Linear Acceleration. A partire da Android 8.0, il sistema ha limitato l'accesso in background ai sensori per migliorare la privacy.
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensorList: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)
sensorList.forEach { sensor ->
Log.d("Sensori", "${sensor.name} — ${sensor.type}")
}
Non tutti i dispositivi hanno lo stesso set di sensori. Un'applicazione deve verificare la disponibilità di un sensore specifico prima di registrare un listener. L'Emulatore Android supporta solo un set limitato di sensori — accelerometro e magnetometro. Testare altri sensori richiede un dispositivo fisico. A partire da Android 12, le applicazioni devono dichiarare l'uso dei sensori nel manifest.
Android classifica tutti i sensori in tre categorie: Motion, Position e Environment. I sensori Motion includono accelerometro, giroscopio e podometro. I sensori Position includono magnetometro e orientamento. I sensori Environment includono luce, pressione, temperatura e umidità.
| Categoria | Sensori | Tipo (costante) | Fisico/Virtuale |
|---|---|---|---|
| Motion | Accelerometro | TYPE_ACCELEROMETER | Fisico |
| Motion | Giroscopio | TYPE_GYROSCOPE | Fisico |
| Motion | Podometro | TYPE_STEP_COUNTER | Fisico |
| Motion | Gravity | TYPE_GRAVITY | Virtuale |
| Position | Magnetometro | TYPE_MAGNETIC_FIELD | Fisico |
| Position | Rotation Vector | TYPE_ROTATION_VECTOR | Virtuale |
| Environment | Luce | TYPE_LIGHT | Fisico |
| Environment | Pressione | TYPE_PRESSURE | Fisico |
L'accelerometro misura l'accelerazione in m/s² lungo tre assi — X, Y e Z. I valori includono la gravità (9,8 m/s² lungo l'asse Z a riposo). Il giroscopio misura la velocità angolare in rad/s — la velocità di rotazione del dispositivo attorno a ciascun asse. La combinazione di questi due sensori viene utilizzata in navigazione, giochi e applicazioni 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) {}
}
Il magnetometro (TYPE_MAGNETIC_FIELD) misura il campo magnetico in microtesla (µT) lungo tre assi. Viene utilizzato come bussola digitale — in combinazione con l'accelerometro, determina l'azimut del dispositivo. Rotation Vector è un sensore virtuale che fonde i dati del giroscopio, dell'accelerometro e del magnetometro per una determinazione precisa dell'orientamento.
Il sensore di luce (TYPE_LIGHT) misura il livello di luce ambientale in lux (lx). Viene utilizzato per la regolazione automatica della luminosità dello schermo. Il sensore di pressione (TYPE_PRESSURE) misura la pressione atmosferica in ettopascal (hPa) — utilizzato nelle applicazioni di navigazione per determinare l'altitudine sul livello del mare.
Sensors API è costruito su un'architettura client-server. L'applicazione funge da client e SensorManager da servizio di sistema Android. Quando l'applicazione registra un listener tramite registerListener, SensorManager comunica con HAL (Hardware Abstraction Layer) — un driver di sensore di basso livello che funziona a livello del kernel Linux.
Il driver HAL riceve i dati grezzi dal chip hardware, filtra il rumore e li invia lungo lo stack — attraverso SensorService (processo di sistema) all'applicazione. I dati vengono passati come oggetto SensorEvent contenente un array di valori float values e un timestamp in nanosecondi. La frequenza degli eventi dipende dalla modalità di consegna selezionata.
Durante la registrazione di un listener, lo sviluppatore specifica il ritardo desiderato tra gli eventi utilizzando le costanti SENSOR_DELAY_NORMAL (200 ms), SENSOR_DELAY_UI (60 ms), SENSOR_DELAY_GAME (20 ms) e SENSOR_DELAY_FASTEST (0 ms — frequenza massima). La frequenza effettiva può differire — il sistema ottimizza il consumo energetico.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.registerListener(
this,
sensor,
SensorManager.SENSOR_DELAY_GAME
)
A partire da Android 2.3, i sensori supportano la modalità batch — gli eventi si accumulano in un buffer FIFO e vengono consegnati in un unico lotto. Ciò consente al processore di rimanere più a lungo in modalità sospensione, riducendo il consumo energetico fino al 60%. La dimensione del buffer dipende dal chip del sensore ed è specificata nel campo Sensor.fifoMaxEventCount.
SensorManager è un servizio di sistema disponibile tramite getSystemService(Context.SENSOR_SERVICE). Fornisce metodi per ottenere un elenco di sensori, ottenere un sensore predefinito specifico e registrare/cancellare listener. SensorManager è un singleton — una singola istanza per l'intera applicazione.
Prima di utilizzare un sensore, è necessario verificarne la disponibilità. Il metodo getDefaultSensor(type) restituisce null se il sensore non è presente sul dispositivo. Ottenere null senza verifica causerà una NullPointerException durante la registrazione di un listener. Il metodo getSensorList(type) restituisce un elenco di tutti i sensori.
fun checkSensorAvailability(type: Int): Boolean {
val sensorManager =
getSystemService(Context.SENSOR_SERVICE) as SensorManager
return sensorManager.getDefaultSensor(type) != null
}
// Uso:
if (checkSensorAvailability(Sensor.TYPE_GYROSCOPE)) {
Log.d("Sensore", "Giroscopio disponibile")
}
Un listener viene registrato tramite registerListener(listener, sensor, delay). Importante: è necessario cancellare il listener nel metodo onPause() tramite unregisterListener(listener). In caso contrario, l'applicazione continuerà a ricevere eventi del sensore, scaricando la batteria anche in background. Android 8+ mostra un avviso in logcat sui listener non cancellati.
Il metodo onAccuracyChanged(sensor, accuracy) viene chiamato quando la precisione del sensore cambia. Valori: SENSOR_STATUS_ACCURACY_HIGH, MEDIUM, LOW e UNRELIABLE. Quando si riceve UNRELIABLE, i dati del sensore devono essere ignorati fino al ripristino della precisione. Ad esempio, il magnetometro richiede calibrazione — agitare il dispositivo con un movimento a otto.
Vediamo esempi pratici di utilizzo di Sensors API in applicazioni Android con Kotlin. Il primo esempio — determinare l'orientamento dello schermo utilizzando l'accelerometro. Il secondo — leggere i dati del magnetometro con calibrazione. Il terzo — un rilevatore di passi usando il podometro.
Una combinazione di accelerometro e magnetometro viene utilizzata per determinare l'orientamento. Il metodo SensorManager.getRotationMatrix() calcola la matrice di rotazione e getOrientation() estrae gli angoli pitch, roll e azimuth. Azimuth — l'angolo rispetto al nord magnetico in radianti.
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())
Il podometro (TYPE_STEP_COUNTER) restituisce il numero totale di passi effettuati dall'utente dall'ultimo riavvio del dispositivo. Il sensore funziona a livello hardware — è attivo anche quando l'applicazione non è in esecuzione. Per ottenere i passi per sessione, è necessario salvare il valore iniziale e calcolare la differenza.
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("Passi", "Passi per sessione: $sessionSteps")
}
}
Il sensore di luce consente di adattare l'interfaccia alle condizioni ambientali. In condizioni di scarsa illuminazione (meno di 10 lx), è possibile passare alla modalità scura. In pieno sole (oltre 10000 lx), è possibile aumentare il contrasto. Per filtrare il rumore viene utilizzata una media mobile degli ultimi 5 valori.
Android fornisce diversi sensori virtuali che non hanno un equivalente hardware diretto. Un sensore virtuale calcola le sue letture basandosi su una combinazione di sensori fisici. Ciò riduce il carico per lo sviluppatore — il sistema stesso implementa algoritmi di fusione dati.
Il sensore Gravity (TYPE_GRAVITY) estrae la componente gravitazionale dalle letture dell'accelerometro utilizzando un filtro passa-basso. Linear Acceleration (TYPE_LINEAR_ACCELERATION), al contrario, rimuove la gravità e lascia solo l'accelerazione lineare del dispositivo. La somma di Gravity e Linear Acceleration fornisce le letture grezze dell'accelerometro.
Rotation Vector — il sensore virtuale più complesso. Combina i dati del giroscopio (cambiamenti ad alta frequenza), dell'accelerometro (vettore di gravità) e del magnetometro (orientamento rispetto al nord). Il risultato è un quaternione che descrive l'orientamento assoluto del dispositivo nello spazio. Viene utilizzato in applicazioni AR e visori VR.
Game Rotation Vector — una versione semplificata di Rotation Vector senza utilizzare il magnetometro. Ciò fornisce una minore precisione dell'azimut ma una maggiore frequenza di aggiornamento e stabilità. È raccomandato per i giochi dove la bassa latenza è importante piuttosto che l'orientamento assoluto rispetto al nord.
I sensori sono tra i componenti del dispositivo che consumano più energia. L'accelerometro e il giroscopio alla massima frequenza di campionamento possono scaricare la batteria in 3–4 ore di funzionamento continuo. Ottimizzare l'uso dei sensori è un compito critico per qualsiasi applicazione che utilizzi Sensors API.
Non utilizzare SENSOR_DELAY_FASTEST inutilmente. Per le animazioni dell'interfaccia, SENSOR_DELAY_UI (60 ms) è sufficiente. Per il rilevamento dell'orientamento dello schermo — SENSOR_DELAY_NORMAL (200 ms). Più alta è la frequenza, più tempo il processore trascorre in stato attivo. La differenza tra NORMAL e FASTEST è fino a 10x nel consumo energetico.
A partire da Android 8.0 (API 26), le applicazioni in background ricevono eventi dei sensori a frequenza ridotta. In Android 12+, l'accesso in background ai sensori Motion e Position richiede l'autorizzazione BODY_SENSORS_BACKGROUND. Cancellare il listener quando l'applicazione passa in background — questo prolunga la durata della batteria del dispositivo.
Utilizzare l'elaborazione batch tramite il metodo registerListener(listener, sensor, delay, maxReportLatencyUs). Il parametro maxReportLatencyUs imposta la latenza massima di consegna degli eventi in microsecondi. Con un valore di 1000000 (1 secondo), gli eventi si accumulano nel buffer FIFO del sensore e vengono consegnati una volta al secondo — il processore si riattiva meno frequentemente.
Domande frequenti
Il set minimo è un accelerometro e un magnetometro. Questi due sensori sono presenti su oltre il 95% dei dispositivi. Giroscopio, sensore di luce e sensore di prossimità — sul 70–80% dei modelli moderni. Altri sensori (pressione, temperatura, umidità, podometro) sono meno comuni e dipendono dalla fascia di prezzo del dispositivo.
TYPE_ACCELEROMETER restituisce l'accelerazione totale inclusa la gravità (9,8 m/s²). TYPE_LINEAR_ACCELERATION restituisce l'accelerazione esclusa la gravità — solo l'accelerazione del movimento del dispositivo. Se il dispositivo è fermo, l'accelerometro mostrerà 9,8 m/s² lungo l'asse Z, mentre Linear Acceleration mostrerà 0 su tutti gli assi.
Utilizzare getPackageManager().hasSystemFeature() con le costanti appropriate: FEATURE_SENSOR_ACCELEROMETER, FEATURE_SENSOR_GYROSCOPE, FEATURE_SENSOR_PROXIMITY e altre. Un metodo alternativo è chiamare getDefaultSensor(type) e verificare se il risultato è null. Il primo metodo è preferibile per la verifica durante l'inizializzazione.
I dati grezzi del sensore contengono rumore. Per attenuarli, utilizzare un filtro passa-basso: newValue = alpha * rawValue + (1 — alpha) * previousValue. Un coefficiente alpha di 0,1–0,3 fornisce un buon equilibrio tra reattività e smoothness. Per il giroscopio, viene applicato anche un filtro passa-alto per rimuovere la deriva dello zero.
Sì, ma con limitazioni. A partire da Android 8.0, la frequenza degli eventi del sensore viene ridotta per le applicazioni in background. A partire da Android 12, è richiesta l'autorizzazione BODY_SENSORS_BACKGROUND per l'accesso ai sensori in background. Per il lavoro in background, si consiglia di utilizzare un Foreground Service con una notifica.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche