2013-05-15 2 views
8

Sto implementando una demo TIMER, con vibrazione (in una condizione particolare), quando premo start il mio timer inizia a funzionare .. e quando lo interrompo usando il pulsante stop, semplicemente si ferma.Rileva il movimento con precisione utilizzando l'accelerometro in Android

Ora devo integrare una funzionalità, quando la persona sposta il dispositivo (mentre il timer è in esecuzione), dovrebbe reimpostare il timer. Funziona piuttosto bene, ma la funzionalità dell'accelerometro non funziona in modo assolutamente accurato. Ha bisogno di uno scatto veloce per resettare il timer.

Suggerisco una buona soluzione per lo stesso.

Ecco il mio codice

public class SensorAccelerometer implements SensorEventListener { 

    private Context context; 
    private SensorManager sensorManager; 
    private Sensor accelerometer; 
    private TextView timelabel; 
    private Handler mHandler; 
    Runnable run; 

    private float mLastX, mLastY, mLastZ; 
    private final float NOISE = (float) 3.0; 

    public SensorAccelerometer(Context context) { 

    } 


    public SensorAccelerometer(Context context,TextView timelabel, Handler mHandler2, Runnable mUpdateTimeTask) { 
     // TODO Auto-generated constructor stub 

     this.context = context; 
     this.timelabel = timelabel; 
     this.mHandler = mHandler2; 
     this.run = mUpdateTimeTask; 

     initialiseSensor(); 
    } 


    public void initialiseSensor(){ 
     sensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); 
     accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ALL); 
     sensorManager.registerListener(this, accelerometer,SensorManager.SENSOR_DELAY_NORMAL); 
    } 

    public void unregisterSensor(){ 
     sensorManager.unregisterListener(this); 
     Toast.makeText(context, "Sensor Stopped..", Toast.LENGTH_SHORT).show(); 
    } 


    public void onAccuracyChanged(Sensor sensor, int accuracy) { 

    } 

    public void onSensorChanged(SensorEvent event) { 
    float x = event.values[0]; 
    float y = event.values[1]; 
    float z = event.values[2]; 

    mAccelLast=mAccelCurrent; 

    mAccelCurrent = FloatMath.sqrt(x*x + y*y + z*z); 
    float delta = mAccelCurrent - mAccelLast; 
    mAccel = mAccel * 0.9f + delta; 

    if(mAccel>0.5){ 
     TimerActivity.mStartTime = SystemClock.uptimeMillis(); 
     mHandler.removeCallbacks(run); 
     mHandler.postDelayed(run, 100); 
    } 

}

Timer Attività

public class TimerActivity extends Activity { 

    public static long mStartTime = 0L; 
    private TextView mTimerLabel; 

    private Handler mHandler = new Handler(); 

    String timerStop1; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     mTimerLabel = (TextView) findViewById(R.id.textTimer); 

     Button timerStartButton = (Button) findViewById(R.id.btnTimer);  
     timerStartButton.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View view){ 

       if(mStartTime == 0L){ 
        mStartTime = SystemClock.uptimeMillis(); 
        mHandler.removeCallbacks(mUpdateTimeTask); 
        mHandler.postDelayed(mUpdateTimeTask, 100); 

        //activating the sensor and the acclerometer 
        SensorAccelerometer acc = new SensorAccelerometer(view.getContext(), mTimerLabel,mHandler,mUpdateTimeTask); 
       }         
      } 
     }); 

     Button timerStopButton = (Button) findViewById(R.id.btnTimerStop);  
     timerStopButton.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View view){ 

       mHandler.removeCallbacks(mUpdateTimeTask); 
       mTimerLabel.setText(timerStop1); 
       mStartTime = 0L; 

       SensorAccelerometer scc = new SensorAccelerometer(view.getContext(),mTimerLabel,mHandler,mUpdateTimeTask); 
       scc.unregisterSensor(); 
      } 
     }); 

    } 


    private Runnable mUpdateTimeTask = new Runnable(){ 

     public void run() { 

      final long start = mStartTime; 
      long millis = SystemClock.uptimeMillis()- start; 

      int seconds = (int) (millis/1000); 
      int minutes = seconds/60; 
      seconds = seconds % 60; 

      mTimerLabel.setText("" + minutes + ":" 
            + String.format("%02d", seconds));      

      timerStop1 = minutes + ":" 
         + String.format("%02d", seconds); 

      mHandler.postDelayed(this, 200);    

     } 
    }; 

    protected void onPause() { 
     super.onPause(); 
     SensorAccelerometer scc = new SensorAccelerometer(this,mTimerLabel,mHandler,mUpdateTimeTask); 
     scc.unregisterSensor(); 
    }; 

} 

risposta

6

Penso che la fase successiva nello sviluppo della tua app sia quella di esaminare i valori di accelerazione prodotti in un foglio di calcolo. Io uso Excel per questo, ma qualsiasi strumento che può produrre grafici farà. Così alterare onSensorChanged() a qualcosa di simile

public void onSensorChanged(SensorEvent event) { 
    float x = event.values[0]; 
    float y = event.values[1]; 
    float z = event.values[2]; 

    float mAccelCurrent = FloatMath.sqrt(x*x + y*y + z*z); 
    float mAccel = mAccel * 0.9f + mAccelCurrent * 0.1f; 
    Log.d("onSensorChanged",System.currentTimeMillis()+","+mAccelCurrent +","+mAccel); 

} 

e quindi è possibile catturare l'currentTime, mAccelCurrent e mAccel nel meccanismo di registrazione di Android. In alternativa, crea il tuo file di testo, scrivi i valori lì e apri il file in uno strumento in grado di produrre grafici. Dai grafici, puoi quindi decidere quali valori utilizzare per il trigger.

+0

La mia semplice domanda è come controllare i dati di inclinazione, (quando il dispositivo è inclinato) e voglio eseguire un set di codice su di esso. avete qualche soluzione per quanto riguarda il codice di cui sopra .. –

+0

@stocasticamente. La mia domanda è la stessa di sopra –

+0

Ho pensato che volevi usare i dati dell'accelerometro per rilevare il movimento. Per fare ciò, è necessario comprendere i dati, quindi la necessità di registrarli e guardarli. Se vuoi solo controllare quando il dispositivo è inclinato è molto più semplice. Ad esempio, vedere il mio risponditore [collegamento] (http://stackoverflow.com/questions/16571798/android-device-angle-on-vertical-axis-while-device-stays-still/16572641#16572641). L'angolo di inclinazione è probabilmente quello che stai cercando. – Stochastically

2

due suggerimenti, e un pensiero:

  1. Per comportamento coerente, si dovrebbe guardare la lunghezza del event.values ​​vector, ovvero Math.sqrt(x*x+y*y+z*z), anziché i singoli valori. Matematicamente, è Math.sqrt(x*x+y*y+z*z) che è indipendente dal tuo sistema di coordinate, cioè come il dispositivo è orientato rispetto al terreno ecc, mentre i numeri individuali x, y, z non lo sono.
  2. La tua app attuale cerca modifiche in accelerazione. Invece, penso che dovresti cercare un'alta accelerazione, ovvero valori elevati di Math.sqrt(x*x+y*y+z*z).
  3. Ho recentemente scritto this answer sull'utilizzo degli accelerometri per un contapassi, e penso che potresti trovare interessante.

+0

Hai fornito un'ottima risposta, ma non sono in grado di capire cosa devo fare per controllare il movimento del dispositivo. Dove dovrei cambiare il mio codice ... in modo che se una persona cambia leggermente la posizione del dispositivo, dovrei farlo. –

+0

I miei commenti 1 e 2 si riferiscono entrambi all'implementazione di 'onSensorChanged (evento SensorEvent)'. Le prime 3 linee vanno bene, dove si imposta x, yez, ma poi è necessario (1) ottenere 'len = Math.sqrt (x * x + y * y + z * z)'. e (2) determinare se 'len' è molto più grande del solito ecc. – Stochastically

+2

Non penso che modificare la domanda in questo modo sia una buona idea, perché la mia risposta e la nostra conversazione ora hanno meno senso per gli altri. Inoltre, la tua modifica è incompleta perché variabili come mAccel non sono dichiarate da nessuna parte. Dovresti iniziare una nuova domanda se hai ancora problemi. Detto questo, sembra che tu stia cercando di rendere "mAccel" un valore livellato di "mAccelCurrent" in un modo piuttosto strano. Invece suggerisco 'mAccel = mAccel * 0.9f + mAccelCurrent * 0.1f'. Oltre a ciò, penso che dovresti registrare mAccel e mAccelCurrent in un file, esaminare i risultati e decidere cosa fare da quello. – Stochastically