La maggior parte dei dispositivi Android è dotata di sensori integrati che misurano il movimento, l'orientamento e le varie condizioni ambientali. Questi sensori sono in grado di fornire dati non elaborati con elevata precisione e precisione e sono utili se vuoi monitorare il movimento o il posizionamento tridimensionale dei dispositivi oppure i cambiamenti nell'ambiente circostante vicino a un dispositivo. Ad esempio, un gioco potrebbe monitorare le letture del sensore di gravità di un dispositivo per dedurre gesti e movimenti complessi dell'utente, come inclinazione, scuotimento, rotazione o oscillazione. Allo stesso modo, un'applicazione meteo potrebbe utilizzare il sensore di temperatura e il sensore di umidità di un dispositivo per calcolare e segnalare il punto di rugiada, oppure un'applicazione di viaggio potrebbe utilizzare il sensore del campo geomagnetico e l'accelerometro per segnalare il rilevamento di una bussola.
Consulta le seguenti risorse correlate:
La piattaforma Android supporta tre ampie categorie di sensori:
- Sensori di movimento
Questi sensori misurano le forze di accelerazione e di rotazione lungo tre assi. Questa categoria include accelerometri, sensori di gravità, giroscopi e sensori di vettori di rotazione.
- Sensori ambientali
Questi sensori misurano vari parametri ambientali, come pressione e temperatura dell'aria ambiente, illuminazione e umidità. Questa categoria include barometri, fotometri e termometri.
- Sensori di posizione
Questi sensori misurano la posizione fisica di un dispositivo. Questa categoria include sensori di orientamento e magnetometri.
Puoi accedere ai sensori disponibili sul dispositivo e acquisire dati non elaborati dei sensori utilizzando il framework dei sensori Android. Il framework dei sensori offre diverse classi e interfacce che ti aiutano a eseguire un'ampia gamma di attività correlate ai sensori. Ad esempio, puoi utilizzare la struttura dei sensori per:
- Determinare quali sensori sono disponibili su un dispositivo.
- Determina le capacità di un singolo sensore, ad esempio portata massima, produttore, requisiti di alimentazione e risoluzione.
- Acquisire i dati non elaborati del sensore e definire la velocità minima di acquisizione dei dati del sensore.
- Registra e annulla la registrazione dei listener di eventi dei sensori che monitorano le modifiche dei sensori.
Questo argomento fornisce una panoramica dei sensori disponibili sulla piattaforma Android. Offre inoltre un'introduzione alla struttura dei sensori.
Introduzione ai sensori
La struttura dei sensori Android ti consente di accedere a molti tipi di sensori. Alcuni di questi sensori sono basati su hardware, altri su software. I sensori basati su hardware sono componenti fisici integrati in un telefono o tablet. I dati derivano dalla misurazione diretta di proprietà ambientali specifiche, come l'accelerazione, l'intensità del campo geomagnetico o il cambiamento angolare. I sensori basati su software non sono dispositivi fisici, sebbene imitano i sensori basati su hardware. I sensori basati su software ricavano i propri dati da uno o più sensori basati su hardware e a volte sono chiamati sensori virtuali o sensori sintetici. Il sensore di accelerazione lineare e il sensore di gravità sono esempi di sensori basati su software. La tabella 1 riassume i sensori supportati dalla piattaforma Android.
Pochi dispositivi Android dispongono di ogni tipo di sensore. Ad esempio, la maggior parte dei dispositivi portatili e dei tablet dispone di un accelerometro e di un magnetometro, ma un numero inferiore di dispositivi dispone di barometri o termometri. Inoltre, un dispositivo può avere più sensori di un determinato tipo. Ad esempio, un dispositivo può avere due sensori di gravità, ognuno con un raggio d'azione diverso.
Tabella 1. Tipi di sensori supportati dalla piattaforma Android.
Sensore | Tipo | Descrizione | Utilizzi comuni |
---|---|---|---|
TYPE_ACCELEROMETER |
Hardware | Misura la forza di accelerazione, in m/s2, applicata a un dispositivo su tutti e tre gli assi fisici (x, y e z), inclusa la forza di gravità. | Rilevamento dei movimenti (scuoti, inclinazione e così via). |
TYPE_AMBIENT_TEMPERATURE |
Hardware | Misura la temperatura ambiente di una stanza in gradi Celsius (°C). Vedi la nota riportata di seguito. | Monitoraggio della temperatura dell'aria. |
TYPE_GRAVITY |
Software o hardware | Misura la forza di gravità, in m/s2, applicata a un dispositivo su tutti e tre gli assi fisici (x, y, z). | Rilevamento dei movimenti (scuoti, inclinazione e così via). |
TYPE_GYROSCOPE |
Hardware | Misura la velocità di rotazione di un dispositivo in rad/s intorno a ciascuno dei tre assi fisici (x, y e z). | Rilevamento rotazione (spin, turn, ecc.). |
TYPE_LIGHT |
Hardware | Misura il livello di luce ambientale (illuminazione) in lx. | Controllo della luminosità dello schermo. |
TYPE_LINEAR_ACCELERATION |
Software o hardware | Misura la forza di accelerazione in m/s2 applicata a un dispositivo su tutti e tre gli assi fisici (x, y e z), escludendo la forza di gravità. | Monitoraggio dell'accelerazione lungo un singolo asse. |
TYPE_MAGNETIC_FIELD |
Hardware | Misura il campo geomagnetico ambientale per tutti e tre gli assi fisici (x, y, z) in μT. | Creazione di una bussola. |
TYPE_ORIENTATION |
streaming | Misura i gradi di rotazione fatti da un dispositivo intorno a tutti e tre gli assi fisici (x, y, z).
A partire dal livello API 3, puoi ottenere la matrice di inclinazione e la matrice di rotazione per un dispositivo utilizzando il sensore di gravità e il sensore di campo geomagnetico in combinazione con il metodo getRotationMatrix() . |
Determinazione della posizione del dispositivo. |
TYPE_PRESSURE |
Hardware | Misura la pressione dell'aria ambiente in hPa o mbar. | Monitoraggio delle variazioni della pressione atmosferica. |
TYPE_PROXIMITY |
Hardware | Misura la vicinanza di un oggetto in cm rispetto allo schermo di un dispositivo. Questo sensore viene solitamente utilizzato per determinare se il telefono è rivolto verso l'orecchio di una persona. | Posizione del telefono durante una chiamata. |
TYPE_RELATIVE_HUMIDITY |
Hardware | Misura l'umidità relativa ambiente in percentuale (%). | Monitoraggio del punto di rugiada, dell'umidità assoluta e dell'umidità relativa. |
TYPE_ROTATION_VECTOR |
Software o hardware | Misura l'orientamento di un dispositivo fornendo i tre elementi del vettore di rotazione del dispositivo. | Rilevamento dei movimenti e rilevamento della rotazione. |
TYPE_TEMPERATURE |
Hardware | Misura la temperatura del dispositivo in gradi Celsius (°C). L'implementazione dei sensori varia a seconda del dispositivo e questo sensore è stato sostituito con il sensore TYPE_AMBIENT_TEMPERATURE nel livello API 14 |
Monitoraggio delle temperature. |
Framework sensori
Puoi accedere a questi sensori e acquisire dati non elaborati dei sensori utilizzando il framework dei sensori Android.
Il framework dei sensori fa parte del pacchetto android.hardware
e include le seguenti
classi e interfacce:
SensorManager
- Puoi utilizzare questa classe per creare un'istanza del servizio dei sensori. Questa classe fornisce vari metodi per accedere e elencare i sensori, registrare e annullare la registrazione degli ascoltatori di eventi dei sensori e acquisire informazioni sull'orientamento. Questa classe fornisce inoltre diverse costanti del sensore che vengono utilizzate per segnalare l'accuratezza del sensore, impostare le velocità di acquisizione dati e calibrare i sensori.
Sensor
- Puoi utilizzare questa classe per creare un'istanza di un sensore specifico. Questa classe offre vari metodi che consentono di determinare le funzionalità di un sensore.
SensorEvent
- Il sistema utilizza questa classe per creare un oggetto evento sensore, che fornisce informazioni su un evento sensore. Un oggetto evento sensore include le seguenti informazioni: dati non elaborati del sensore, il tipo di sensore che ha generato l'evento, la precisione dei dati e il timestamp dell'evento.
SensorEventListener
- Puoi utilizzare questa interfaccia per creare due metodi di callback che ricevono notifiche (eventi dei sensori) quando i valori dei sensori cambiano o quando la precisione del sensore cambia.
In un'applicazione tipica, le API relative ai sensori vengono utilizzate per eseguire due attività di base:
- Identificazione dei sensori e delle funzionalità dei sensori
L'identificazione di sensori e funzionalità dei sensori in fase di runtime è utile se l'applicazione ha funzionalità che si basano su funzionalità o tipi di sensori specifici. Ad esempio, potresti voler identificare tutti i sensori presenti su un dispositivo e disattivare le funzionalità dell'applicazione che si basano su sensori non presenti. Allo stesso modo, potresti voler identificare tutti i sensori di un determinato tipo, in modo da poter scegliere l'implementazione del sensore con le prestazioni ottimali per la tua applicazione.
- Monitorare gli eventi dei sensori
Il monitoraggio degli eventi dei sensori è il modo in cui acquisisci i dati non elaborati dei sensori. Un evento del sensore si verifica ogni volta che un sensore rileva una modifica nei parametri che sta misurando. Un evento del sensore fornisce quattro informazioni: il nome del sensore che ha attivato l'evento, il timestamp dell'evento, l'accuratezza dell'evento e i dati non elaborati del sensore che lo hanno attivato.
Disponibilità dei sensori
La disponibilità dei sensori varia da dispositivo a dispositivo, ma può variare anche tra le versioni di Android. Questo perché i sensori Android sono stati introdotti nel corso di diverse versioni della piattaforma. Ad esempio, molti sensori sono stati introdotti in Android 1.5 (livello API 3), ma alcuni non sono stati implementati e non sono stati disponibili per l'utilizzo fino ad Android 2.3 (livello API 9). Analogamente, sono stati introdotti diversi sensori in Android 2.3 (livello API 9) e Android 4.0 (livello API 14). Due sensori sono stati ritirati e sostituiti da sensori migliori e più recenti.
La Tabella 2 riassume la disponibilità di ciascun sensore piattaforma per piattaforma. Sono elencate solo quattro piattaforme perché sono quelle che hanno interessato le modifiche dei sensori. I sensori elencati come deprecati sono ancora disponibili sulle piattaforme successive (a condizione che il sensore sia presente su un dispositivo), in linea con le norme di compatibilità diretta di Android.
Tabella 2. Disponibilità dei sensori per piattaforma.
Sensore | Android 4.0 (livello API 14) |
Android 2.3 (livello API 9) |
Android 2.2 (livello API 8) |
Android 1.5 (livello API 3) |
---|---|---|---|---|
TYPE_ACCELEROMETER |
Sì | Sì | Sì | Sì |
TYPE_AMBIENT_TEMPERATURE |
Sì | n/a | n/d | n/a |
TYPE_GRAVITY |
Sì | Sì | n/a | n/a |
TYPE_GYROSCOPE |
Sì | Sì | n/a1 | n/a1 |
TYPE_LIGHT |
Sì | Sì | Sì | Sì |
TYPE_LINEAR_ACCELERATION |
Sì | Sì | n/a | n/a |
TYPE_MAGNETIC_FIELD |
Sì | Sì | Sì | Sì |
TYPE_ORIENTATION |
Sì2 | Sì2 | Sì2 | Sì |
TYPE_PRESSURE |
Sì | Sì | n/a1 | n/a1 |
TYPE_PROXIMITY |
Sì | Sì | Sì | Sì |
TYPE_RELATIVE_HUMIDITY |
Sì | n/a | n/d | n/a |
TYPE_ROTATION_VECTOR |
Sì | Sì | n/a | n/a |
TYPE_TEMPERATURE |
Sì2 | Sì | Sì | Sì |
1 Questo tipo di sensore è stato aggiunto in Android 1.5 (livello API 3), ma è stato reso disponibile solo per Android 2.3 (livello API 9).
2 Questo sensore è disponibile, ma è stato ritirato.
Identificazione dei sensori e delle capacità dei sensori
Il framework dei sensori Android offre diversi metodi che ti consentono di determinare facilmente in fase di runtime quali sensori sono presenti su un dispositivo. L'API fornisce inoltre metodi che consentono di determinare le funzionalità di ciascun sensore, ad esempio la portata massima, la risoluzione e i requisiti di alimentazione.
Per identificare i sensori che si trovano su un dispositivo, devi prima ottenere un riferimento al servizio dei sensori. Per farlo, crea un'istanza della classe SensorManager
chiamando il metodo getSystemService()
e passando l'argomento SENSOR_SERVICE
. Ecco alcuni esempi:
Kotlin
private lateinit var sensorManager: SensorManager ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
Java
private SensorManager sensorManager; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Successivamente, puoi ottenere un elenco di ogni sensore presente su un dispositivo chiamando il
metodo getSensorList()
e utilizzando la costante TYPE_ALL
. Ecco alcuni esempi:
Kotlin
val deviceSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)
Java
List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
Se vuoi elencare tutti i sensori di un determinato tipo, puoi utilizzare un'altra costante anziché TYPE_ALL
come TYPE_GYROSCOPE
, TYPE_LINEAR_ACCELERATION
o TYPE_GRAVITY
.
Puoi anche determinare se su un dispositivo è presente un tipo specifico di sensore utilizzando il metodo getDefaultSensor()
e trasmettendo la costante di tipo
per un sensore specifico. Se un dispositivo ha più sensori di un determinato tipo, uno dei
sensori deve essere designato come sensore predefinito. Se per un determinato tipo di sensore non esiste un sensore predefinito, la chiamata al metodo restituisce null, il che significa che il dispositivo non dispone di quel tipo di sensore. Ad esempio, il codice seguente controlla se su un dispositivo è presente un magnetometro:
Kotlin
private lateinit var sensorManager: SensorManager ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) { // Success! There's a magnetometer. } else { // Failure! No magnetometer. }
Java
private SensorManager sensorManager; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){ // Success! There's a magnetometer. } else { // Failure! No magnetometer. }
Nota: Android non richiede ai produttori di dispositivi di integrare determinati tipi di sensori nei propri dispositivi basati su Android, pertanto i dispositivi possono avere una vasta gamma di configurazioni dei sensori.
Oltre a elencare i sensori che si trovano su un dispositivo, puoi utilizzare i metodi pubblici della classe Sensor
per determinare le funzionalità e gli attributi dei singoli sensori. Questo è utile se vuoi che l'applicazione si comporti in modo diverso in base ai sensori o alle funzionalità dei sensori disponibili su un dispositivo. Ad esempio, puoi usare i metodi getResolution()
e getMaximumRange()
per ottenere la risoluzione di un sensore e la gamma massima di misurazione. Puoi anche utilizzare il metodo getPower()
per conoscere i requisiti di alimentazione di un sensore.
Due dei metodi pubblici sono particolarmente utili se vuoi ottimizzare l'applicazione per sensori di produttori diversi o versioni diverse di un sensore. Ad esempio, se la tua applicazione ha bisogno di monitorare gesti degli utenti come l'inclinazione e l'oscillazione, puoi creare un insieme di regole di filtro dei dati e ottimizzazioni per i dispositivi più recenti dotati di sensore di gravità di un fornitore specifico e un'altra serie di regole di filtraggio dei dati e ottimizzazioni per i dispositivi che non hanno un sensore di gravità e hanno solo un accelerometro. Il seguente esempio di codice mostra come utilizzare i metodi getVendor()
e getVersion()
per eseguire questa operazione. In questo esempio, stiamo cercando un sensore di gravità che indichi Google LLC come fornitore e abbia il numero di versione 3. Se quel particolare sensore non è presente sul dispositivo, proviamo a utilizzare l'accelerometro.
Kotlin
private lateinit var sensorManager: SensorManager private var mSensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) { val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY) // Use the version 3 gravity sensor. mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 } } if (mSensor == null) { // Use the accelerometer. mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) { sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) } else { // Sorry, there are no accelerometers on your device. // You can't play this game. null } }
Java
private SensorManager sensorManager; private Sensor mSensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mSensor = null; if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){ List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY); for(int i=0; i<gravSensors.size(); i++) { if ((gravSensors.get(i).getVendor().contains("Google LLC")) && (gravSensors.get(i).getVersion() == 3)){ // Use the version 3 gravity sensor. mSensor = gravSensors.get(i); } } } if (mSensor == null){ // Use the accelerometer. if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){ mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); } else{ // Sorry, there are no accelerometers on your device. // You can't play this game. } }
Un altro metodo utile è il metodo getMinDelay()
,
che restituisce l'intervallo di tempo minimo (in microsecondi) che un sensore può utilizzare per rilevare i dati. Qualsiasi sensore che restituisce un valore diverso da zero per il metodo getMinDelay()
è un sensore di streaming. I sensori di streaming rilevano i dati a intervalli regolari e sono stati introdotti in Android 2.3 (Livello API 9). Se un sensore restituisce zero quando chiami il metodo getMinDelay()
, significa che il sensore non è un sensore di flusso perché segnala i dati solo quando si verifica una modifica nei parametri che rileva.
Il metodo getMinDelay()
è utile perché consente di determinare la velocità massima con cui un sensore può acquisire dati. Se determinate funzionalità dell'applicazione richiedono tassi di acquisizione dati elevati o un sensore di streaming, puoi utilizzare questo metodo per determinare se un sensore soddisfa tali requisiti e poi attivare o disattivare le funzionalità pertinenti nella tua applicazione di conseguenza.
Attenzione: la velocità massima di acquisizione dati di un sensore non corrisponde necessariamente a quella con cui il framework del sensore invia i dati del sensore alla tua applicazione. Il framework dei sensori segnala i dati tramite gli eventi dei sensori e diversi fattori influiscono sulla frequenza con cui l'applicazione riceve eventi dei sensori. Per ulteriori informazioni, consulta la sezione Monitoraggio degli eventi dei sensori.
Monitoraggio degli eventi dei sensori
Per monitorare i dati non elaborati dei sensori, devi implementare due metodi di callback che mostrino
l'interfaccia di SensorEventListener
: onAccuracyChanged()
e onSensorChanged()
. Il sistema Android chiama questi metodi ogni volta che si verifica quanto segue:
- La precisione di un sensore cambia.
In questo caso il sistema richiama il metodo
onAccuracyChanged()
, fornendo un riferimento all'oggettoSensor
che è stato modificato e la nuova precisione del sensore. L'accuratezza è rappresentata da una delle quattro costanti di stato:SENSOR_STATUS_ACCURACY_LOW
,SENSOR_STATUS_ACCURACY_MEDIUM
,SENSOR_STATUS_ACCURACY_HIGH
oSENSOR_STATUS_UNRELIABLE
. - Un sensore segnala un nuovo valore.
In questo caso il sistema richiama il metodo
onSensorChanged()
, fornendo un oggettoSensorEvent
. Un oggettoSensorEvent
contiene informazioni sui dati del nuovo sensore, tra cui: l'accuratezza dei dati, il sensore che ha generato i dati, il timestamp in cui i dati sono stati generati e i nuovi dati registrati dal sensore.
Il codice seguente mostra come utilizzare il metodo onSensorChanged()
per monitorare i dati del sensore di luce. Questo esempio mostra i dati non elaborati del sensore in un elemento TextView
che è
definito nel file main.xml come sensor_data
.
Kotlin
class SensorActivity : Activity(), SensorEventListener { private lateinit var sensorManager: SensorManager private var mLight: Sensor? = null public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { // Do something here if sensor accuracy changes. } override fun onSensorChanged(event: SensorEvent) { // The light sensor returns a single value. // Many sensors return 3 values, one for each axis. val lux = event.values[0] // Do something with this sensor value. } override fun onResume() { super.onResume() mLight?.also { light -> sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL) } } override fun onPause() { super.onPause() sensorManager.unregisterListener(this) } }
Java
public class SensorActivity extends Activity implements SensorEventListener { private SensorManager sensorManager; private Sensor mLight; @Override public final void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); } @Override public final void onAccuracyChanged(Sensor sensor, int accuracy) { // Do something here if sensor accuracy changes. } @Override public final void onSensorChanged(SensorEvent event) { // The light sensor returns a single value. // Many sensors return 3 values, one for each axis. float lux = event.values[0]; // Do something with this sensor value. } @Override protected void onResume() { super.onResume(); sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener(this); } }
In questo esempio, il ritardo predefinito dei dati (SENSOR_DELAY_NORMAL
) viene specificato quando viene richiamato il metodo registerListener()
. Il ritardo dei dati (o frequenza di campionamento) controlla l'intervallo con cui gli eventi del sensore vengono inviati alla tua applicazione tramite il metodo di callback onSensorChanged()
. Il ritardo dati predefinito è adatto per monitorare le normali variazioni dell'orientamento dello schermo e utilizza un ritardo di 200.000 microsecondi. Puoi specificare altri ritardi dei dati, ad esempio SENSOR_DELAY_GAME
(ritardo di 20.000 microsecondi), SENSOR_DELAY_UI
(ritardo di 60.000 microsecondi) o SENSOR_DELAY_FASTEST
(ritardo di 0 microsecondi). A partire da Android 3.0 (Livello API 11) puoi anche specificare il ritardo come valore assoluto (in microsecondi).
Il ritardo specificato è solo un ritardo suggerito. Il sistema Android e altre applicazioni possono alterare questo ritardo. Come best practice, devi specificare il ritardo massimo possibile poiché il sistema in genere utilizza un ritardo minore di quello specificato (in altre parole, dovresti scegliere la frequenza di campionamento più lenta che soddisfa ancora le esigenze della tua applicazione). L'utilizzo di un ritardo maggiore impone un carico inferiore al processore e, di conseguenza, consuma meno energia.
Non esiste un metodo pubblico per determinare la frequenza con cui il framework dei sensori invia eventi dei sensori all'applicazione; tuttavia, puoi utilizzare i timestamp associati a ciascun evento del sensore per calcolare la frequenza di campionamento su più eventi. Una volta impostata, non dovrebbe essere necessario modificare la frequenza di campionamento (ritardo). Se per qualche motivo è necessario modificare il ritardo, dovrai annullare la registrazione e registrare nuovamente il listener del sensore.
È inoltre importante notare che questo esempio utilizza i metodi di callback onResume()
e onPause()
per registrare e annullare la registrazione dell'ascoltatore di eventi del sensore. Come best practice, dovresti sempre disattivare i sensori non necessari, in particolare quando la tua attività è in pausa. In caso contrario, la batteria potrebbe scaricarsi in poche ore perché alcuni sensori hanno requisiti di alimentazione considerevoli e consumano rapidamente la batteria. Il sistema
non disattiverà automaticamente i sensori quando lo schermo si spegne.
Gestione di diverse configurazioni dei sensori
Android non specifica una configurazione standard dei sensori per i dispositivi, il che significa che i produttori di dispositivi possono incorporare qualsiasi configurazione di sensori desiderata nei propri dispositivi Android. Di conseguenza, i dispositivi possono includere una varietà di sensori in un'ampia gamma di configurazioni. Se la tua applicazione si basa su un tipo specifico di sensore, devi assicurarti che il sensore sia presente su un dispositivo in modo che l'app possa funzionare correttamente.
Sono disponibili due opzioni per garantire che un determinato sensore sia presente su un dispositivo:
- Rileva i sensori in fase di runtime e abilita o disabilita le funzionalità dell'applicazione in base alle esigenze.
- Utilizzare i filtri di Google Play per scegliere come target dispositivi con configurazioni di sensori specifiche.
Ciascuna opzione è trattata nelle sezioni seguenti.
Rilevamento dei sensori in fase di runtime
Se la tua applicazione utilizza un tipo specifico di sensore, ma non si basa su di esso, puoi utilizzare il framework dei sensori per rilevare il sensore in fase di runtime e quindi disattivare o attivare le funzionalità dell'applicazione in base alle esigenze. Ad esempio, un'applicazione di navigazione potrebbe utilizzare il sensore di temperatura, il sensore di pressione, il sensore GPS e il sensore del campo geomagnetico per visualizzare la temperatura, la pressione barometrica, la posizione e il rilevamento della bussola. Se un dispositivo non dispone di un sensore di pressione, puoi utilizzare il framework dei sensori per rilevare l'assenza del sensore di pressione in fase di runtime e poi disabilitare la porzione dell'UI della tua applicazione che mostra la pressione. Ad esempio, il codice seguente controlla se su un dispositivo è presente un sensore di pressione:
Kotlin
private lateinit var sensorManager: SensorManager ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) { // Success! There's a pressure sensor. } else { // Failure! No pressure sensor. }
Java
private SensorManager sensorManager; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){ // Success! There's a pressure sensor. } else { // Failure! No pressure sensor. }
Utilizzo dei filtri di Google Play per il targeting di configurazioni di sensori specifiche
Se pubblichi la tua applicazione su Google Play, puoi utilizzare l'elemento <uses-feature>
nel file manifest per filtrare l'applicazione dai dispositivi che non hanno la configurazione del sensore appropriata per la tua applicazione. L'elemento <uses-feature>
ha diversi descrittori hardware che ti consentono di filtrare le applicazioni in base alla presenza di sensori specifici. I sensori che puoi elencare includono:
accelerometro, barometro, bussola (campo geomagnetico), giroscopio, luce e prossimità. Di seguito è riportata una voce manifest di esempio che filtra le app che non hanno un accelerometro:
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
Se aggiungi questo elemento e descrittore al file manifest della tua applicazione, gli utenti potranno vedere la tua applicazione su Google Play soltanto se il loro dispositivo dispone di un accelerometro.
Devi impostare il descrittore su android:required="true"
solo se l'applicazione
si basa interamente su un sensore specifico. Se l'applicazione utilizza un sensore per alcune funzionalità, ma continua a funzionare senza il sensore, dovresti elencare il sensore nell'elemento <uses-feature>
, ma impostare il descrittore su android:required="false"
. Ciò contribuisce a garantire che i dispositivi possano installare la tua app anche se non dispongono di quel particolare sensore. Si tratta anche di una best practice per la gestione dei progetti che ti aiuta a tenere traccia delle funzionalità utilizzate dall'applicazione.
Tieni presente che se l'applicazione utilizza un determinato sensore, ma continua a funzionare senza il sensore, è necessario rilevare il sensore in fase di runtime e disattivare o attivare le funzionalità dell'applicazione in base alle esigenze.
Sistema di coordinate dei sensori
In generale, il framework dei sensori utilizza un sistema di coordinate standard a 3 assi per esprimere i valori dei dati. Per la maggior parte dei sensori, il sistema di coordinate viene definito in base allo schermo del dispositivo quando quest'ultimo viene tenuto nell'orientamento predefinito (vedi figura 1). Quando un dispositivo viene tenuto nell'orientamento predefinito, l'asse X è orizzontale e punta a destra, l'asse Y è verticale e punta verso l'alto e l'asse Z punta verso l'esterno dello schermo. In questo sistema, le coordinate dietro lo schermo hanno valori Z negativi. Questo sistema di coordinate viene utilizzato dai seguenti sensori:

Figura 1. Sistema di coordinate (relativo a un dispositivo) utilizzato dall'API Sensor.
- Sensore di accelerazione
- Sensore di gravità
- Giroscopio
- Sensore di accelerazione lineare
- Sensore di campo geomagnetico
L'aspetto più importante da capire riguardo a questo sistema di coordinate è che gli assi non vengono scambiati quando l'orientamento dello schermo del dispositivo cambia, vale a dire che il sistema di coordinate del sensore non cambia mai durante il movimento del dispositivo. Questo comportamento è uguale a quello del sistema di coordinate OpenGL.
Un altro aspetto da comprendere è che l'applicazione non deve presupporre che l'orientamento naturale (predefinito) del dispositivo sia verticale. L'orientamento naturale di molti dispositivi tablet è orizzontale. Inoltre, il sistema di coordinate dei sensori si basa sempre sull'orientamento naturale di un dispositivo.
Infine, se l'applicazione abbina i dati del sensore al display sullo schermo, dovrai utilizzare il metodo getRotation()
per determinare la rotazione dello schermo, quindi utilizzare il metodo remapCoordinateSystem()
per mappare le coordinate del sensore alle coordinate dello schermo. È necessario eseguire questa operazione anche se il file manifest specifica
la visualizzazione solo verticale.
Nota: alcuni sensori e metodi utilizzano un sistema di coordinate relativo al quadro di riferimento del mondo (anziché al quadro di riferimento del dispositivo). Questi sensori e metodi restituiscono dati che rappresentano il movimento o la posizione del dispositivo rispetto alla Terra. Per ulteriori informazioni, consulta il metodo getOrientation()
, il metodo getRotationMatrix()
, Sensore di orientamento e Sensore di rotazione vettoriale.
Limitazione della frequenza dei sensori
Per proteggere le informazioni potenzialmente sensibili degli utenti, se la tua app ha come target Android 12 (livello API 31) o versioni successive, il sistema impone un limite alla frequenza di aggiornamento dei dati di determinati sensori di movimento e di posizione. Questi dati includono valori registrati dall'accelerometro, dal giroscopio e dal sensore di campo geomagnetico del dispositivo.
Il limite di frequenza di aggiornamento dipende dal modo in cui accedi ai dati dei sensori:
- Se chiami il metodo
registerListener()
per monitorare gli eventi del sensore, la frequenza di campionamento del sensore è limitata a 200 Hz. Questo vale per tutte le varianti sovraccaricate del metodoregisterListener()
. - Se utilizzi la classe
SensorDirectChannel
, la frequenza di campionamento del sensore è limitata aRATE_NORMAL
, che solitamente è di circa 50 Hz.
Se la tua app deve raccogliere i dati dei sensori di movimento a una frequenza superiore, devi
dichiarare l'autorizzazione
HIGH_SAMPLING_RATE_SENSORS
come mostrato nel seguente snippet di codice. In caso contrario, se la tua app cerca di raccogliere i dati del sensore di movimento a una velocità superiore senza dichiarare questa autorizzazione, si verifica una SecurityException
.
File AndroidManifest.xml
<manifest ...> <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/> <application ...> ... </application> </manifest>
Best practice per accedere e utilizzare i sensori
Durante la progettazione dell'implementazione del sensore, assicurati di seguire le linee guida discusse in questa sezione. Queste linee guida sono best practice consigliate per chiunque utilizzi il framework dei sensori per accedere ai sensori e acquisire i relativi dati.
Raccogliere solo i dati dei sensori in primo piano
Sui dispositivi con Android 9 (livello API 28) o versioni successive, le app eseguite in background hanno le seguenti limitazioni:
- I sensori che utilizzano la modalità di reporting continua, ad esempio accelerometri e giroscopi, non ricevono eventi.
- I sensori che utilizzano le modalità di generazione dei report al cambiamento o one-shot non ricevono eventi.
Date queste restrizioni, è meglio rilevare gli eventi dei sensori quando l'app è in primo piano o nell'ambito di un servizio in primo piano.
Annulla registrazione dei listener dei sensori
Assicurati di annullare la registrazione del listener di un sensore quando hai finito di utilizzare il sensore o quando l'attività del sensore viene messa in pausa. Se un listener del sensore è registrato e la sua attività viene sospesa, il sensore continuerà ad acquisire dati e utilizzare risorse della batteria, a meno che non annulli la registrazione del sensore. Il codice seguente mostra come utilizzare il metodo onPause()
per annullare la registrazione di un listener:
Kotlin
private lateinit var sensorManager: SensorManager ... override fun onPause() { super.onPause() sensorManager.unregisterListener(this) }
Java
private SensorManager sensorManager; ... @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener(this); }
Per ulteriori informazioni, vedi unregisterListener(SensorEventListener)
.
Esegui test con l'emulatore Android
L'emulatore Android include una serie di controlli dei sensori virtuali che ti consentono di testare sensori quali accelerometro, temperatura ambiente, magnetometro, prossimità, luce e altro ancora.
L'emulatore utilizza una connessione con un dispositivo Android su cui è installata l'app SdkControllerSensor. Tieni presente che questa app è disponibile solo su dispositivi con Android 4.0 (livello API 14) o versioni successive. Se sul dispositivo è installato Android 4.0, deve essere installata la revisione 2. L'app SdkControllerSensor monitora le modifiche apportate ai sensori sul dispositivo e le trasmette all'emulatore. L'emulatore viene poi trasformato in base ai nuovi valori che riceve dai sensori sul tuo dispositivo.
Puoi visualizzare il codice sorgente per l'app SdkControllerSensor nel seguente percorso:
$ your-android-sdk-directory/tools/apps/SdkController
Per trasferire i dati tra il tuo dispositivo e l'emulatore, svolgi i seguenti passaggi:
- Verifica che il debug USB sia abilitato sul tuo dispositivo.
- Collega il dispositivo alla macchina di sviluppo tramite un cavo USB.
- Avvia l'app SdkControllerSensor sul dispositivo.
- Nell'app, seleziona i sensori che vuoi emulare.
Esegui questo comando
adb
:- Avvia l'emulatore. Ora dovresti essere in grado di applicare le trasformazioni all'emulatore spostando il dispositivo.
$ adb forward tcp:1968 tcp:1968
Nota: se i movimenti che esegui sul dispositivo fisico non stanno trasformando l'emulatore, prova a eseguire di nuovo il comando adb
dal passaggio 5.
Per ulteriori informazioni, consulta la guida all'emulatore Android.
Non bloccare il metodo onSensorChanged()
I dati dei sensori possono variare molto spesso, il che significa che il sistema potrebbe chiamare il metodo onSensorChanged(SensorEvent)
molto spesso. Come best practice, devi fare il meno possibile all'interno del metodo onSensorChanged(SensorEvent)
per non bloccarlo. Se la tua applicazione richiede di filtrare i dati o di ridurre i dati dei sensori, devi eseguire queste operazioni al di fuori del metodo onSensorChanged(SensorEvent)
.
Evita di utilizzare metodi o tipi di sensori obsoleti
Diversi metodi e costanti sono stati ritirati.
In particolare, il tipo di sensore TYPE_ORIENTATION
è stato deprecato. Per ottenere i dati sull'orientamento, usa invece il metodo getOrientation()
. Analogamente, il tipo di sensore TYPE_TEMPERATURE
è stato deprecato. Sui dispositivi che eseguono Android 4.0 dovresti usare invece il tipo di sensore TYPE_AMBIENT_TEMPERATURE
.
Verifica i sensori prima di utilizzarli
Prima di tentare di acquisire dati, verifica sempre che su un dispositivo sia presente un sensore. Non dare per scontato che un sensore esista solo perché si tratta di un sensore utilizzato di frequente. I produttori di dispositivi non sono tenuti a fornire sensori specifici nei loro dispositivi.
Scegli attentamente i ritardi del sensore
Quando registri un sensore con il metodo registerListener()
, assicurati di scegliere una tariffa di consegna adatta all'applicazione o al caso d'uso. I sensori possono fornire dati a velocità molto elevate. Consentendo al sistema di inviare dati aggiuntivi che non ti servono, vengono usate risorse di sistema e viene consumata la batteria.