La maggior parte dei dispositivi Android è dotata di sensori integrati che misurano il movimento, l'orientamento e varie condizioni ambientali. Questi sensori sono in grado di fornire dati non elaborati con precisione e accuratezza elevata e sono utili se vuoi monitorare il movimento o il posizionamento tridimensionale del dispositivo o se vuoi monitorare le variazioni nell'ambiente ambiente vicino a un dispositivo. Ad esempio, un gioco potrebbe tenere traccia delle letture del sensore di gravità di un dispositivo per dedurre gesti e movimenti complessi dell'utente come inclinazione, scuotimento, rotazione o swing. Analogamente, un'applicazione meteo potrebbe utilizzare i sensori di temperatura e di umidità di un dispositivo per calcolare e registrare il punto di rugiada, mentre un'applicazione di viaggio potrebbe utilizzare il sensore di campo geomagnetico e l'accelerometro per segnalare il rilevamento della 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 su tre assi. Questa categoria include accelerometri, sensori di gravità, giroscopi e sensori vettoriali di rotazione.
- Sensori ambientali
Questi sensori misurano vari parametri ambientali, come la temperatura e la pressione dell'aria, l'illuminazione e l'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. La struttura dei sensori offre diverse classi e interfacce che consentono di eseguire un'ampia varietà di attività relative ai sensori. Ad esempio, puoi utilizzare la struttura dei sensori per:
- Determina quali sensori sono disponibili su un dispositivo.
- Determina le capacità di un singolo sensore, come la portata massima, il produttore, i requisiti di alimentazione e la risoluzione.
- Acquisisci dati non elaborati dei sensori e definisci la velocità minima alla quale acquisisci dati dei sensori.
- Registra e annulla la registrazione dei listener di eventi dei sensori che monitorano le variazioni dei sensori.
Questo argomento fornisce una panoramica dei sensori disponibili sulla piattaforma Android. Fornisce anche un'introduzione alla struttura dei sensori.
Introduzione ai sensori
Il framework dei sensori Android ti consente di accedere a molti tipi di sensori. Alcuni di questi sensori sono basati su hardware, mentre altri sono basati su software. I sensori basati su hardware sono componenti fisici integrati in uno smartphone o in un tablet. Ricava i dati misurando direttamente specifiche proprietà ambientali, come l'accelerazione, l'intensità del campo geomagnetico o la variazione angolare. I sensori basati su software non sono dispositivi fisici, anche se imitano 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 sensori di ogni tipo. Ad esempio, la maggior parte dei telefoni e dei tablet è dotata di un accelerometro e un magnetometro, ma meno dispositivi dispongono di barometri o termometri. Inoltre, un dispositivo può avere più di un sensore di un determinato tipo. Ad esempio, un dispositivo può avere due sensori di gravità, ognuno con una portata diversa.
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 (scosse, inclinazione e così via). |
TYPE_AMBIENT_TEMPERATURE |
Hardware | Misura la temperatura ambientale in una stanza in gradi Celsius (°C). Vedi nota 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 (scosse, inclinazione e così via). |
TYPE_GYROSCOPE |
Hardware | Misura la velocità di rotazione di un dispositivo in rad/s attorno a ciascuno dei tre assi fisici (x, y e z). | Rilevamento della rotazione (rotazione, rotazione e così via). |
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), esclusa 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 effettuati da un dispositivo attorno 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 di un dispositivo utilizzando il sensore di gravità e il sensore di campo geomagnetico insieme al 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 alla schermata di un dispositivo. Questo sensore viene generalmente utilizzato per determinare se lo smartphone viene tenuto avvicinato all'orecchio di una persona. | Posizione dello smartphone durante una chiamata. |
TYPE_RELATIVE_HUMIDITY |
Hardware | Misura l'umidità relativa dell'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 della rotazione. |
TYPE_TEMPERATURE |
Hardware | Misura la temperatura del dispositivo in gradi Celsius (°C). L'implementazione dei sensori varia da un dispositivo all'altro e questo sensore è stato sostituito con il sensore TYPE_AMBIENT_TEMPERATURE nell'API Livello 14 |
Monitoraggio delle temperature. |
Struttura del sensore
Puoi accedere a questi sensori e acquisire dati non elaborati dei sensori utilizzando il framework dei sensori di Android.
Il framework dei sensori fa parte del pacchetto android.hardware
e include le seguenti
classi e interfacce:
SensorManager
- Puoi usare questa lezione per creare un'istanza del servizio dei sensori. Questa lezione offre vari metodi per accedere ed elencare i sensori, registrare e annullare la registrazione degli ascoltatori di eventi dei sensori e acquisire informazioni sull'orientamento. Questa classe fornisce anche diverse costanti dei sensori utilizzate per segnalare la precisione dei sensori, impostare le frequenze di acquisizione dei dati e calibrare i sensori.
Sensor
- Puoi usare questa lezione per creare un'istanza di un sensore specifico. Questa lezione offre diversi metodi che consentono di determinare le capacità di un sensore.
SensorEvent
- Il sistema utilizza questa classe per creare un oggetto evento sensore, che fornisce informazioni su un evento del sensore. Un oggetto evento del sensore include le seguenti informazioni: i dati non elaborati del sensore, il tipo di sensore che ha generato l'evento, l'accuratezza 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 dei sensori cambia.
In un'applicazione tipica, vengono usate queste API relative ai sensori per eseguire due attività di base:
- Identificare i sensori e le funzionalità dei sensori
L'identificazione di sensori e funzionalità dei sensori in fase di runtime è utile se la tua 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 disabilitare le funzionalità delle applicazioni che si basano su sensori non presenti. Analogamente, potresti voler identificare tutti i sensori di un determinato tipo in modo da poter scegliere l'implementazione dei sensori 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. Ogni volta che un sensore rileva un cambiamento nei parametri che sta misurando, si verifica un evento del sensore. 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 in base alla versione di Android. Questo perché i sensori Android sono stati introdotti nel corso di diverse release della piattaforma. Ad esempio, in Android 1.5 (livello API 3) sono stati introdotti molti sensori, ma alcuni non sono stati implementati e non erano 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 più recenti e migliori.
La Tabella 2 riassume la disponibilità di ciascun sensore piattaforma per piattaforma. Sono elencate solo quattro piattaforme perché sono quelle che hanno comportato i cambiamenti dei sensori. I sensori elencati come deprecati sono comunque disponibili su piattaforme successive (a condizione che il sensore sia presente su un dispositivo), in linea con i criteri di compatibilità avanzata di Android.
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/D1 | N/D1 |
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/D1 | N/D1 |
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 non era disponibile per l'uso fino ad Android 2.3 (livello API 9).
2 Questo sensore è disponibile, ma è stato deprecato.
Identificazione dei sensori e delle loro funzionalità
Il framework dei sensori Android offre diversi metodi che ti consentono di determinare facilmente al momento dell'esecuzione quali sensori sono presenti su un dispositivo. L'API fornisce inoltre metodi che consentono di determinare le capacità di ciascun sensore, come la portata massima, la risoluzione e i requisiti di alimentazione.
Per identificare i sensori presenti su un dispositivo, devi prima ottenere un riferimento al servizio sensori. Per farlo, devi creare 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);
In seguito, puoi ottenere un elenco di tutti i sensori di 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
, ad esempio 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 passando la costante
del tipo per un sensore specifico. Se un dispositivo ha più di un sensore di un determinato tipo, uno dei sensori deve essere designato come sensore predefinito. Se non esiste un sensore predefinito per un determinato tipo di sensore, la chiamata al metodo restituisce null, il che significa che il dispositivo non dispone di quel tipo di sensore. Ad esempio, il seguente codice verifica se sul 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 integrare particolari tipi di sensori nei loro dispositivi basati su Android, quindi i dispositivi possono avere un'ampia gamma di configurazioni dei sensori.
Oltre a elencare i sensori presenti su un dispositivo, puoi utilizzare i metodi pubblici della classe Sensor
per determinare le capacità e gli attributi dei singoli sensori. Ciò è utile se vuoi che la tua applicazione si comporti in modo diverso in base ai sensori o alle funzionalità dei sensori disponibili su un dispositivo. Ad esempio, puoi utilizzare i metodi getResolution()
e getMaximumRange()
per ottenere la risoluzione di un sensore e il raggio massimo di misurazione. Puoi anche usare il
metodo getPower()
per ottenere i requisiti di alimentazione di un sensore.
Due dei metodi pubblici sono particolarmente utili se vuoi ottimizzare l'applicazione per sensori di diversi produttori o versioni diverse di un sensore. Ad esempio, se la tua applicazione deve monitorare i gesti dell'utente, come l'inclinazione e lo scuotimento, potresti 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 altro insieme di regole di filtro dei dati e ottimizzazioni per i dispositivi che non dispongono di un sensore di gravità e dispongono di solo un accelerometro. Il seguente esempio di codice mostra come utilizzare i metodi getVendor()
e getVersion()
a questo scopo. In questo esempio, stiamo cercando un sensore di gravità che indichi Google LLC come fornitore e
ha un numero di versione pari a 3. Se quel sensore specifico non è presente sul dispositivo, proviamo a usare 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
flusso. I sensori di flusso rilevano i dati a intervalli regolari e sono stati introdotti in Android 2.3 (livello API 9). Se un sensore restituisce lo zero quando chiami il metodo getMinDelay()
, significa che il sensore
non è un sensore di flusso perché segnala i dati solo quando c'è una variazione dei
parametri che sta rilevando.
Il metodo getMinDelay()
è utile perché consente di determinare la velocità massima alla quale un sensore può acquisire dati. Se alcune funzionalità della tua applicazione richiedono elevate percentuali di acquisizione dati o un sensore di flussi di dati, puoi utilizzare questo metodo per determinare se un sensore soddisfa questi requisiti, quindi attivare o disattivare le funzionalità pertinenti nell'applicazione di conseguenza.
Attenzione: la frequenza massima di acquisizione dei dati di un sensore non corrisponde necessariamente alla velocità con cui la struttura del sensore invia i dati dei sensori alla tua applicazione. Il framework dei sensori segnala i dati tramite gli eventi dei sensori e diversi fattori influenzano la frequenza con cui l'applicazione riceve gli 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 esposti tramite
l'interfaccia 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()
, fornendoti un riferimento all'oggettoSensor
che è stato modificato e alla nuova accuratezza del sensore. La precisione è 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()
, fornendoti un oggettoSensorEvent
. Un oggettoSensorEvent
contiene informazioni sui nuovi dati del sensore, tra cui: l'accuratezza dei dati, il sensore che ha generato i dati, il timestamp con cui sono stati generati i dati e i nuovi dati registrati dal sensore.
Il seguente codice mostra come utilizzare il metodo onSensorChanged()
per monitorare i dati del
sensore di luce. Questo esempio mostra i dati non elaborati dei sensori in un elemento TextView
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 dei dati predefinito (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 all'applicazione
tramite il metodo di callback onSensorChanged()
. Il ritardo dei dati predefinito è adatto per monitorare le variazioni tipiche 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 specificare anche il ritardo come valore assoluto (in microsecondi).
Il ritardo specificato è solo un ritardo suggerito. Il sistema Android e altre applicazioni possono modificare questo ritardo. Come best practice, devi specificare il ritardo maggiore possibile perché il sistema in genere utilizza un ritardo inferiore a quello specificato (vale a dire, devi scegliere la frequenza di campionamento più lenta che soddisfi ancora le esigenze della tua applicazione). L'utilizzo di un ritardo maggiore impone un carico inferiore sul processore e quindi un consumo minore.
Non esiste un metodo pubblico per determinare la frequenza con cui il framework dei sensori invia eventi dei sensori alla tua 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 è necessario modificare la frequenza di campionamento (ritardo). Se per qualche motivo devi modificare il ritardo, dovrai annullare la registrazione e registrare di nuovo il listener del sensore.
È anche importante notare che in questo esempio vengono utilizzati i metodi di callback onResume()
e onPause()
per registrare e annullare la registrazione dell'ascoltatore degli eventi dei sensori. Come best practice, dovresti sempre disattivare i sensori di cui non hai bisogno, soprattutto quando la tua attività è sospesa. In caso contrario, la batteria potrebbe scaricarsi entro poche ore perché alcuni sensori hanno requisiti di alimentazione notevoli e possono esaurire rapidamente la batteria. Il sistema
non disattiva automaticamente i sensori allo spegnimento dello schermo.
Gestione di diverse configurazioni dei sensori
Android non specifica una configurazione standard dei sensori per i dispositivi, perciò i produttori possono incorporare qualsiasi configurazione dei sensori che desiderano nei loro dispositivi basati su Android. Di conseguenza, i dispositivi possono includere vari 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 affinché l'app possa funzionare correttamente.
Esistono due opzioni per garantire la presenza di un determinato sensore su un dispositivo:
- Rileva i sensori in fase di runtime e attiva o disattiva le funzionalità dell'applicazione in base alle esigenze.
- Usa i filtri di Google Play per scegliere come target dispositivi con configurazioni specifiche dei sensori.
Ciascuna opzione viene discussa nelle sezioni seguenti.
Rilevamento dei sensori in fase di esecuzione
Se la tua applicazione utilizza un tipo specifico di sensore, ma non si basa su questo, puoi utilizzare il framework dei sensori per rilevare il sensore in fase di runtime, quindi disabilitare o attivare le funzionalità dell'applicazione in base alle tue esigenze. Ad esempio, un'applicazione di navigazione potrebbe utilizzare i sensori di temperatura, sensore di pressione, GPS e campo geomagnetico per visualizzare la temperatura, la pressione barometrica, la posizione e l'orientamento della bussola. Se un dispositivo non dispone di un sensore di pressione, puoi utilizzare la struttura del sensore per rilevare l'assenza del sensore in fase di esecuzione e poi disabilitare la parte dell'interfaccia utente dell'applicazione che mostra la pressione. Ad esempio, il seguente codice verifica se sul 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. }
Usare i filtri di Google Play per scegliere configurazioni specifiche dei sensori come target
Se pubblichi la tua applicazione su Google Play, puoi usare l'elemento <uses-feature>
nel file manifest per filtrare l'applicazione in base ai 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 è riportato un esempio di voce del file manifest che filtra le app prive di accelerometro:
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
Se aggiungi questo elemento e descrittore al file manifest dell'applicazione, gli utenti vedranno 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 la tua applicazione utilizza un sensore per alcune funzionalità, ma
continua a funzionare senza il sensore, devi elencare il sensore nell'elemento <uses-feature>
, ma impostare il descrittore su android:required="false"
. In questo modo avrai la certezza che
i dispositivi possano installare la tua app anche se non dispongono di quel particolare sensore. Questa è anche una best practice per la gestione dei progetti che ti consente di tenere traccia delle funzionalità utilizzate dalla tua applicazione.
Tieni presente che se la tua applicazione utilizza un determinato sensore, ma continua a funzionare senza il sensore, devi rilevare il sensore in fase di runtime e disabilitare o attivare le funzionalità dell'applicazione in base alle tue esigenze.
Sistema di coordinate del sensore
In generale, la struttura 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 il dispositivo è tenuto nell'orientamento predefinito (vedi figura 1). Quando un dispositivo viene mantenuto nell'orientamento predefinito, l'asse X è orizzontale e punta a destra, l'asse Y è verticale e rivolto verso l'alto e l'asse Z è rivolto verso l'esterno della superficie dello schermo. In questo sistema, le coordinate dietro lo schermo hanno valori Z negativi. Questo sistema di coordinate viene utilizzato dai seguenti sensori:
- Sensore di accelerazione
- Sensore di gravità
- Giroscopio
- Sensore di accelerazione lineare
- Sensore di campo geomagnetico
Il punto più importante da comprendere su questo sistema di coordinate è che gli assi non vengono scambiati quando l'orientamento dello schermo del dispositivo cambia, ovvero il sistema di coordinate del sensore non cambia mai mentre il dispositivo si muove. È uguale al sistema di coordinate OpenGL.
Un altro punto da capire è che l'applicazione non deve presupporre che l'orientamento naturale (predefinito) di un dispositivo sia verticale. L'orientamento naturale di molti tablet è orizzontale. Inoltre, il sistema di coordinate dei sensori si basa sempre sull'orientamento naturale di un dispositivo.
Infine, se l'applicazione associa i dati dei sensori al display sullo schermo, devi 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. Devi 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 frame di riferimento del mondo (e non a quello del dispositivo). Questi sensori e metodi restituiscono dati che rappresentano il movimento o la posizione del dispositivo rispetto alla Terra. Per ulteriori informazioni, vedi i metodi getOrientation()
, il metodo getRotationMatrix()
, Orientation
Sensor e Rotazione Vector
Sensor.
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 pone un limite alla frequenza di aggiornamento dei dati provenienti da determinati sensori di movimento e sensori di posizione. Questi dati includono i 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 del sensore:
- 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 con sovraccarico del metodoregisterListener()
. - Se utilizzi la classe
SensorDirectChannel
, la frequenza di campionamento del sensore è limitata aRATE_NORMAL
, che di solito è di circa 50 Hz.
Se la tua app ha bisogno di raccogliere i dati dei sensori di movimento a una velocità maggiore, devi
dichiarare l'autorizzazione
HIGH_SAMPLING_RATE_SENSORS
, come mostrato nello snippet di codice seguente. In caso contrario, se l'app tenta
di raccogliere i dati dei sensori di movimento a una velocità maggiore senza dichiarare questa autorizzazione,
si verifica un SecurityException
.
<manifest ...> <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/> <application ...> ... </application> </manifest>
Best practice per l'accesso e l'utilizzo dei sensori
Durante la progettazione dell'implementazione dei sensori, assicurati di seguire le linee guida descritte in questa sezione. Queste linee guida sono best practice consigliate a chiunque utilizzi il framework dei sensori per accedere ai sensori e acquisirne i dati.
Raccogli i dati dei sensori solo 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 segnalazione continua, come accelerometri e giroscopi, non ricevono eventi.
- I sensori che utilizzano le modalità di reporting in caso di modifica o one-shot non ricevono eventi.
Date queste limitazioni, è meglio rilevare gli eventi dei sensori quando la tua app è in primo piano o nell'ambito di un servizio in primo piano.
Annulla la 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 si interrompe. Se un listener di sensori è registrato e la sua attività viene messa in pausa, il sensore continuerà ad acquisire dati e a utilizzare le risorse della batteria, a meno che non annulli la registrazione del sensore. Il seguente codice 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 per sensori virtuali che ti consentono di testare sensori come accelerometro, temperatura ambiente, magnetometro, prossimità, luce e altri.
L'emulatore utilizza una connessione con un dispositivo Android su cui è in esecuzione l'app SdkControllerSensor. Tieni presente che questa app è disponibile solo su dispositivi con Android 4.0 (livello API 14) o versioni successive. Se nel dispositivo è in esecuzione Android 4.0, deve avere la Revisione 2 installata. L'app SdkControllerSensor monitora le variazioni dei sensori sul dispositivo e le trasmette all'emulatore. L'emulatore viene quindi trasformato in base ai nuovi valori che riceve dai sensori del tuo dispositivo.
Puoi visualizzare il codice sorgente per l'app SdkControllerSensor in questa posizione:
$ your-android-sdk-directory/tools/apps/SdkController
Per trasferire i dati tra il tuo dispositivo e l'emulatore, segui questi passaggi:
- Verifica che il debug USB sia attivato sul dispositivo.
- Collega il dispositivo alla macchina di sviluppo usando un cavo USB.
- Avvia l'app SdkControllerSensor sul tuo dispositivo.
- Nell'app, seleziona i sensori che vuoi emulare.
Esegui questo comando
adb
:- Avvia l'emulatore. Ora dovresti essere in grado di applicare trasformazioni all'emulatore spostando il dispositivo.
$ adb forward tcp:1968 tcp:1968
Nota: se i movimenti che fai al dispositivo fisico non trasformano l'emulatore, prova a eseguire di nuovo il comando adb
dal passaggio 5.
Per ulteriori informazioni, consulta la guida dell'emulatore Android.
Non bloccare il metodo onSensorChanged()
I dati dei sensori possono variare con una frequenza elevata, il che significa che il sistema potrebbe chiamare il metodo onSensorChanged(SensorEvent)
abbastanza spesso. Come best practice, dovresti fare il meno possibile all'interno del metodo onSensorChanged(SensorEvent)
per non bloccarlo. Se la tua applicazione richiede l'applicazione di filtri o riduzione dei dati dei sensori, devi eseguire questa operazione al di fuori del metodo onSensorChanged(SensorEvent)
.
Evita di utilizzare metodi o tipi di sensori deprecati
Diversi metodi e costanti sono stati ritirati.
In particolare, il tipo di sensore TYPE_ORIENTATION
è stato deprecato. Per ottenere dati sull'orientamento, devi usare il metodo getOrientation()
. Allo stesso modo, il
tipo di sensore TYPE_TEMPERATURE
è stato ritirato. Dovresti usare
il tipo di sensore TYPE_AMBIENT_TEMPERATURE
sui dispositivi
con Android 4.0.
Verifica i sensori prima di utilizzarli
Verifica sempre che su un dispositivo sia presente un sensore prima di tentare di acquisirne i dati. Non dare per scontato che un sensore esista semplicemente perché è un sensore di uso frequente. I produttori non sono tenuti a fornire sensori specifici nei loro dispositivi.
Scegli con attenzione i ritardi dei sensori
Quando registri un sensore con il metodo registerListener()
, assicurati di scegliere una velocità 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 sprecate le risorse del sistema e consumato batteria.