Utilizzo dell'accelerometro su Android

In questo tutorial, esploreremo come utilizzare l'accelerometro, uno dei numerosi sensori hardware degli smartphone moderni, in un'applicazione Android. Spiegherò cos'è un accelerometro e perché potrebbe essere qualcosa che vuoi sfruttare nelle tue applicazioni Android.

introduzione

Prima dell'alba degli smartphone, una delle poche applicazioni di componenti hardware in grado di interagire era la tastiera. Ma i tempi sono cambiati e l'interazione con i componenti hardware sta diventando sempre più comune.

L'uso dei gesti spesso sembra più naturale dell'interazione con un'interfaccia utente tramite mouse e tastiera. Questo è particolarmente vero per i dispositivi touch, come smartphone e tablet. Trovo che usare i gesti possa dare vita a un'applicazione Android, rendendola più interessante ed eccitante per l'utente.

Parecchie app stanno facendo uso dell'accelerometro. Ad esempio, dai un'occhiata a questi modelli di app su Envato Market, che includono un gioco di corse di velocità e uno shaker di numeri casuali.

In questo tutorial, useremo un gesto che trovi in ​​alcune applicazioni mobili, il gesto di scuotere. Useremo il gesto della scossa per generare casualmente sei numeri della Lotteria e visualizzarli sullo schermo usando una bella animazione.

1. Per iniziare

Passaggio 1: Impostazione del progetto

Avvia un nuovo progetto Android nel tuo IDE preferito (Integrated Development Environment) per lo sviluppo Android. Per questo tutorial, userò IntelliJ IDEA.

Se il tuo IDE supporta lo sviluppo Android, avrà creato a Principale classe per te. Il nome di questa classe può variare a seconda dell'IDE che stai utilizzando. Il Principale la classe gioca un ruolo chiave quando viene lanciata la tua applicazione. Il tuo IDE dovrebbe anche aver creato un file di layout principale che il Principale class usa per creare l'interfaccia utente dell'applicazione.

Poiché utilizzeremo un gesto di scuotimento, è consigliabile bloccare l'orientamento del dispositivo. Ciò garantirà che l'interfaccia utente dell'applicazione non passi continuamente da verticale a orizzontale. Apri il file manifest del progetto e imposta il file orientamento schermo opzione a ritratto.

     

Passaggio 2: impostazione del sensore

Con il nostro progetto, è tempo di sporcarci le mani e scrivere del codice. Al momento, la principale classe di attività ha un onCreate metodo in cui impostiamo il layout principale invocando setContentView come mostrato di seguito.

la classe pubblica Main estende l'attività / ** chiamata quando l'attività viene creata per la prima volta. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); 

A seconda dell'IDE che si sta utilizzando, potrebbe essere necessario aggiungere alcune istruzioni di importazione a Main.java, il file in cui il tuo Principale vite di classe La maggior parte degli IDE inserirà queste istruzioni di importazione per te, ma voglio assicurarmi che siamo sulla stessa pagina prima di continuare. La prima dichiarazione di importazione, importare android.app.Activity, importa il Attività classe mentre la seconda dichiarazione di importazione, importa android.os.Bundle, importa il impacchettare classe. La terza dichiarazione di importazione, com.example.R, contiene le definizioni per le risorse dell'applicazione. Questa dichiarazione di importazione differirà da quella che vedi qui sotto in quanto dipende dal nome del tuo pacco.

importare android.app.Activity; importare android.os.Bundle; import com.example.R;

Nel prossimo passo, faremo leva sul SensorEventListener interfaccia, che è dichiarata nell'SDK di Android. Per usare il SensorEventListener interfaccia, il Principale la classe di attività deve implementarla come mostrato nello snippet di codice seguente. Se dai un'occhiata all'aggiornato Principale classe di attività, troverai che io uso il attrezzi parola chiave per dire al compilatore che il Principale la classe implementa il SensorEventListener interfaccia.

public class Main extends Activity implementa SensorEventListener / ** Chiamato quando l'attività viene creata per la prima volta. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); 

Per usare il SensorEventListener interfaccia, è necessario aggiungere un'altra dichiarazione di importazione come mostrato di seguito. La maggior parte degli IDE aggiungerà in modo intelligente la dichiarazione di importazione per te, quindi probabilmente non dovrai preoccuparti di questo.

import android.hardware.SensorEventListener;

Dal momento in cui aggiorni il Principale implementazione di classe come mostrato sopra, vedrai apparire alcuni errori. Questo non è sorprendente poiché abbiamo bisogno di due implementare due metodi richiesti del SensorEventListener interfaccia.

Se utilizzi IntelliJ IDEA, ti verrà chiesto di aggiungere questi metodi obbligatori quando fai clic sull'errore. Se stai utilizzando un IDE diverso, questo comportamento potrebbe essere diverso. Aggiungiamo i due metodi richiesti a mano come mostrato nel frammento di codice qui sotto. Assicurati di aggiungere questi metodi in Principale classe e al di fuori del onCreate metodo.

@Override public void onSensorChanged (evento SensorEvent)  @Override public void onAccuracyChanged (Sensore sensore, precisione int) 

Diamo un'occhiata al onSensorChanged metodo. Useremo questo metodo per rilevare il gesto di scuotimento. Il onSensorChanged il metodo viene invocato ogni volta che il sensore incorporato rileva una modifica. Questo metodo viene richiamato ripetutamente ogni volta che il dispositivo è in movimento. Per usare il Sensore e SensorEvent classi, aggiungiamo due istruzioni di importazione aggiuntive come mostrato di seguito.

importare android.hardware.Sensor; import android.hardware.SensorEvent;

Prima di implementare onSensorChanged, dobbiamo dichiarare due variabili private nel Principale classe, senSensorManager di tipo SensorManager e senAccelerometer di tipo Sensore.

SensorManager privato senSensorManager; sensore privato Accelerometro;

Il SensorManager la classe è dichiarata in android.hardware.SensorManager. Se visualizzi degli errori, verifica che il file SensorManager anche la classe viene importata.

importare android.hardware.SensorManager;

Nel onCreate metodo, inizializziamo le variabili che abbiamo appena dichiarato e registriamo un listener. Dai un'occhiata all'implementazione aggiornata del onCreate metodo.

@Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); senSensorManager = (SensorManager) getSystemService (Context.SENSOR_SERVICE); senAccelerometer = senSensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER); senSensorManager.registerListener (questo, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 

Per inizializzare il SensorManager esempio, invochiamo getSystemService per recuperare il sistema SensorManager istanza, che a sua volta utilizziamo per accedere ai sensori del sistema. Il getSystemService il metodo viene utilizzato per ottenere un riferimento a un servizio del sistema passando il nome del servizio. Con il gestore dei sensori a nostra disposizione, invochiamo un riferimento all'accelerometro del sistema getDefaultSensor sul gestore del sensore e passando il tipo di sensore a cui siamo interessati. Quindi registriamo il sensore utilizzando uno dei SensorManagerI metodi pubblici, registerListener. Questo metodo accetta tre argomenti, il contesto dell'attività, un sensore e la frequenza con cui vengono forniti gli eventi del sensore.

public class Main extends Implementa sensorEventListener private SensorManager senSensorManager; sensore privato Accelerometro; / ** Chiamato quando l'attività viene creata per la prima volta. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); senSensorManager = (SensorManager) getSystemService (Context.SENSOR_SERVICE); senAccelerometer = senSensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER); senSensorManager.registerListener (questo, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);  @Override public void onSensorChanged (SensorEvent sensorEvent)  @Override public void onAccuracyChanged (Sensore sensore, precisione int) 

Ci sono altri due metodi che abbiamo bisogno di sovrascrivere, onPause e onResume. Questi sono metodi del Principale classe. È buona norma annullare la registrazione del sensore quando l'applicazione si iberna e registrare di nuovo il sensore quando l'applicazione riprende. Dai uno sguardo ai frammenti di codice qui sotto per avere un'idea di come funziona in pratica.

protected void onPause () super.onPause (); senSensorManager.unregisterListener (questo); 
protected void onResume () super.onResume (); senSensorManager.registerListener (questo, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 

Passaggio 3: rilevamento del gesto di scuotimento

Ora possiamo iniziare a concentrarci sulla carne dell'applicazione. Richiederà un po 'di matematica per capire quando un gesto di scuotimento ha luogo. La maggior parte della logica andrà nel onSensorChanged metodo. Iniziamo dichiarando alcune variabili nel nostro Principale classe. Dai uno sguardo allo snippet di codice qui sotto.

private long lastUpdate = 0; private float last_x, last_y, last_z; private static final int SHAKE_THRESHOLD = 600;

Esaminiamo ora l'implementazione di onSensorChanged metodo. Prendiamo un riferimento al Sensore istanza usando il SensorEvent istanza che ci è passata. Come puoi vedere nello snippet di codice qui sotto, controlliamo due volte di ottenere un riferimento al tipo di sensore corretto, l'accelerometro del sistema.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) 

Il prossimo passo è quello di estrarre la posizione del dispositivo nello spazio, il X, y, e z asse. Dai un'occhiata all'immagine qui sotto per capire meglio a cosa mi riferisco. Il X l'asse definisce il movimento laterale, mentre il y l'asse definisce il movimento verticale. Il z l'asse è un po 'più complicato in quanto definisce il movimento dentro e fuori il piano definito dal X e y assi.


Per ottenere i valori di ciascun asse, chiediamo all'evento sensore i suoi valori come mostrato di seguito. Gli eventi valori l'attributo è una matrice di float.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; 

I sensori del sistema sono incredibilmente sensibili. Quando si tiene in mano un dispositivo, esso è costantemente in movimento, indipendentemente da quanto sia ferma la mano. Il risultato è che il onSensorChanged il metodo è invocato più volte al secondo. Non abbiamo bisogno di tutti questi dati, quindi dobbiamo assicurarci di campionare solo un sottoinsieme dei dati che riceviamo dall'accelerometro del dispositivo. Memorizziamo l'ora corrente del sistema (in millisecondi) curtime e controllare se più di 100 sono passati millisecondi dall'ultima volta onSensorChanged è stato invocato.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; long curTime = System.currentTimeMillis (); if ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; 

L'ultimo pezzo del puzzle sta rilevando se il dispositivo è stato scosso o meno. Noi usiamo il Matematica classe per calcolare la velocità del dispositivo come mostrato di seguito. Il staticamente dichiarato SHAKE_THRESHOLD variabile è usata per vedere se un gesto di scuotimento è stato rilevato o meno. Modifica SHAKE_THRESHOLD aumenta o diminuisce la sensibilità, quindi sentitevi liberi di giocare con il suo valore.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; long curTime = System.currentTimeMillis (); if ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; float speed = Math.abs (x + y + z - last_x - last_y - last_z) / diffTime * 10000; if (speed> SHAKE_THRESHOLD)  last_x = x; last_y = y; last_z = z; 

2. Termina l'applicazione della lotteria

Ora abbiamo un'applicazione in grado di rilevare un movimento della scossa usando l'accelerometro. Finiamo questo progetto usando il gesto della scossa per scegliere sei numeri casuali della lotteria. Ti mostrerò come generare un numero casuale tra 1 e 49, ma sei libero di modificare la mia implementazione per farlo funzionare con il modo in cui la lotteria viene giocata nel tuo paese.

Iniziamo impostando il file di layout principale dell'applicazione che useremo per l'interfaccia utente. Come puoi vedere qui sotto, utilizzo sei layout di frame con uno sfondo di un'immagine di una palla.

                        

Ogni layout di frame contiene una vista testuale che mostrerà un numero di lotteria generato casualmente. Si noti che ogni layout di cornice e vista testo ha un id per assicurarci di poterli consultare in seguito.

Con il layout principale pronto per l'uso, rivisitiamo il Principale classe. Iniziamo creando getRandomNumber, un metodo privato per generare sei numeri casuali tra 1 e 49.

private void getRandomNumber () ArrayList numbersGenerated = new ArrayList (); per (int i = 0; i < 6; i++)  Random randNumber = new Random(); int iNumber = randNumber.nextInt(48) + 1; if(!numbersGenerated.contains(iNumber))  numbersGenerated.add(iNumber);  else  i--;   

Per prima cosa creiamo un Lista di array istanza, che usiamo per memorizzare i sei numeri in. In ogni ciclo del per loop, traiamo vantaggio da Java Casuale classe per generare un numero casuale. Per assicurarci di ottenere un numero compreso tra 1 e 49, noi aggiungiamo 1 al risultato. Il passo successivo è verificare se il numero generato è già presente nell'elenco di array, poiché desideriamo solo numeri univoci nell'elenco di array.

Si noti che potrebbe essere necessario aggiungere altre due istruzioni di importazione per mantenere il compilatore felice.

import java.util.ArrayList; import java.util.Random;

Il passo finale è visualizzare il numero generato casualmente nell'interfaccia utente. Otteniamo un riferimento alle viste di testo che abbiamo creato in precedenza e popoliamo ogni visualizzazione di testo con un numero casuale. Inoltre, aggiungiamo un'animazione pulita ai layout dei fotogrammi, ma sentitevi liberi di omettere o modificare l'animazione.

private void getRandomNumber () ArrayList numbersGenerated = new ArrayList (); per (int i = 0; i < 6; i++)  Random randNumber = new Random(); int iNumber = randNumber.nextInt(48) + 1; if(!numbersGenerated.contains(iNumber))  numbersGenerated.add(iNumber);  else  i--;   TextView text = (TextView)findViewById(R.id.number_1); text.setText(""+numbersGenerated.get(0)); text = (TextView)findViewById(R.id.number_2); text.setText(""+numbersGenerated.get(1)); text = (TextView)findViewById(R.id.number_3); text.setText(""+numbersGenerated.get(2)); text = (TextView)findViewById(R.id.number_4); text.setText(""+numbersGenerated.get(3)); text = (TextView)findViewById(R.id.number_5); text.setText(""+numbersGenerated.get(4)); text = (TextView)findViewById(R.id.number_6); text.setText(""+numbersGenerated.get(5)); FrameLayout ball1 = (FrameLayout) findViewById(R.id.ball_1); ball1.setVisibility(View.INVISIBLE); FrameLayout ball2 = (FrameLayout) findViewById(R.id.ball_2); ball2.setVisibility(View.INVISIBLE); FrameLayout ball3 = (FrameLayout) findViewById(R.id.ball_3); ball3.setVisibility(View.INVISIBLE); FrameLayout ball4 = (FrameLayout) findViewById(R.id.ball_4); ball4.setVisibility(View.INVISIBLE); FrameLayout ball5 = (FrameLayout) findViewById(R.id.ball_5); ball5.setVisibility(View.INVISIBLE); FrameLayout ball6 = (FrameLayout) findViewById(R.id.ball_6); ball6.setVisibility(View.INVISIBLE); Animation a = AnimationUtils.loadAnimation(this, R.anim.move_down_ball_first); ball6.setVisibility(View.VISIBLE); ball6.clearAnimation(); ball6.startAnimation(a); ball5.setVisibility(View.VISIBLE); ball5.clearAnimation(); ball5.startAnimation(a); ball4.setVisibility(View.VISIBLE); ball4.clearAnimation(); ball4.startAnimation(a); ball3.setVisibility(View.VISIBLE); ball3.clearAnimation(); ball3.startAnimation(a); ball2.setVisibility(View.VISIBLE); ball2.clearAnimation(); ball2.startAnimation(a); ball1.setVisibility(View.VISIBLE); ball1.clearAnimation(); ball1.startAnimation(a); 

Avremo bisogno di aggiungere qualche altra dichiarazione di importazione per far funzionare tutto questo. Dai uno sguardo allo snippet di codice qui sotto.

importa android.view.View; importare android.view.animation.Animation; importare android.view.animation.AnimationUtils; import android.widget.FrameLayout; import android.widget.TextView;

Per quanto riguarda le animazioni, dai un'occhiata al contenuto del file di animazione qui sotto. Si noti che è necessario creare un anim cartella nella directory delle risorse del progetto e nominarla move_down_ball_first.xml. Regolando i valori del scala elemento, puoi modificare la durata dell'animazione e la posizione di ogni palla.

   

Tutto ciò che resta da fare è chiamare getRandomNumber nel onSensorChanged nel Principale classe. Dai un'occhiata alla completa implementazione di onSensorChanged mostrato sotto.

public void onSensorChange (SensorEvent sensorEvent) Sensor mySensor = sensorEvent.sensor; if (mySensor.getType () == Sensor.TYPE_ACCELEROMETER) float x = sensorEvent.values ​​[0]; float y = sensorEvent.values ​​[1]; float z = sensorEvent.values ​​[2]; long curTime = System.currentTimeMillis (); if ((curTime - lastUpdate)> 100) long diffTime = (curTime - lastUpdate); lastUpdate = curTime; float speed = Math.abs (x + y + z - last_x - last_y - last_z) / diffTime * 10000; if (speed> SHAKE_THRESHOLD) getRandomNumber ();  last_x = x; last_y = y; last_z = z; 

Conclusione

In questo tutorial, ti ho mostrato come funziona l'accelerometro e come puoi utilizzarlo per rilevare un gesto di scuotimento. Naturalmente, ci sono molti altri casi d'uso per l'accelerometro. Con una comprensione di base della rilevazione dei gesti usando l'accelerometro, ti incoraggio a sperimentare con l'accelerometro per vedere cos'altro puoi fare con esso.

Se lavori molto con lo sviluppo di Android, probabilmente ti imbatterai in situazioni in cui hai bisogno di aiuto con un aspetto particolare che non è la tua specialità. In tal caso, prova ad assumere uno degli sviluppatori esperti di app su Envato Studio per completare il lavoro in modo rapido e affidabile.