2013-05-15 8 views
8

Wdrażam TIMER demonstracyjny, z Wibracją (w szczególnym stanie), Kiedy naciskam start, mój timer zaczyna działać ... a kiedy zatrzymam go za pomocą przycisku stop, po prostu się zatrzymuje.Wykrywaj ruch Dokładnie za pomocą akcelerometru w Androidzie

Teraz muszę zintegrować funkcjonalność, gdy osoba przesuwa urządzenie (gdy timer jest uruchomiony), powinien zresetować licznik czasu. Działa całkiem nieźle, ale funkcja akcelerometru nie działa absolutnie dokładnie. Wymaga szybkiego szarpnięcia, aby zresetować timer.

Zaproponuj mi dobre rozwiązanie dla tego samego.

Oto mój kod

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); 
    } 

}

czasowy aktywny

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(); 
    }; 

} 

Odpowiedz

6

Myślę, że następnym etapem rozwoju aplikacji jest spojrzenie na wartości przyspieszenia, które są generowane w arkuszu kalkulacyjnym. Używam do tego programu Excel, ale zrobi to dowolne narzędzie, które może tworzyć wykresy. Więc zmieniać onSensorChanged() coś jak

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); 

} 

a następnie można uchwycić CurrentTime, mAccelCurrent i mAccel do Android mechanizmu rejestrowania. Możesz również utworzyć własny plik tekstowy, zapisać tam wartości i otworzyć plik w narzędziu, które może generować wykresy. Na wykresach możesz zdecydować, jakie wartości użyć dla wyzwalacza.

+0

Moje proste pytanie brzmi: jak sprawdzić dane pochylenia, (kiedy urządzenie jest przechylone) i chcę wykonać na nim zestaw kodu. czy masz jakieś rozwiązanie dotyczące powyższego kodu .. –

+0

@stochastically. Pytanie moje jest takie samo jak powyżej. –

+0

Myślałem, że chcesz użyć danych z akcelerometru do wykrycia ruchu. Aby to zrobić, musisz zrozumieć dane, stąd potrzeba ich zalogowania i spojrzenia na to. Jeśli chcesz tylko sprawdzić, kiedy urządzenie jest przechylone, to jest o wiele łatwiejsze. Na przykład zobacz mój odpowiednik [link] (http://stackoverflow.com/questions/16571798/android-device-angle-on-onical-axis-while-device-stays-still/16572641#16572641). Kąt pochylenia jest prawdopodobnie tym, czego szukasz. – Stochastically

2

dwie sugestie, i jedna myśl:

  1. Dla konsekwentnego zachowania, należy spojrzeć na długości wektor wartości zdarzeń, tj. Math.sqrt(x*x+y*y+z*z), a nie poszczególne wartości. Matematycznie, to jest niezależne od systemu współrzędnych, tj. Jak urządzenie jest zorientowane względem ziemi, itd., Podczas gdy poszczególne liczby x, y, z nie są.
  2. Twoja bieżąca aplikacja szuka zmian przyspieszenia. Zamiast tego, powinieneś po prostu poszukać wysokiego przyspieszenia, tj. Dużych wartości Math.sqrt(x*x+y*y+z*z).
  3. Ostatnio napisałem: this answer o używaniu akcelerometrów do krokomierza i myślę, że może ci się to wydać interesujące.

+0

Podałeś bardzo dobrą odpowiedź, ale nie jestem w stanie zrozumieć, co powinienem zrobić, aby sprawdzić ruch urządzenia. Gdzie powinienem zmienić mój kod ... tak, że jeśli dana osoba zmieni nieco położenie urządzenia, powinienem go zdobyć. –

+0

Moje komentarze 1 i 2 odnoszą się do implementacji 'onSensorChanged (zdarzenie SensorEvent)'. Twoje pierwsze 3 linie są w porządku, gdzie ustawiasz x, yi z, ale musisz (1) uzyskać 'len = Math.sqrt (x * x + y * y + z * z)'. i (2) określić, czy 'len' jest znacznie większy niż zwykle itp. – Stochastically

+2

Nie wydaje mi się, że edytowanie tego pytania jest dobrym pomysłem, ponieważ moja odpowiedź i nasza rozmowa mają teraz mniejszy sens dla innych. Ponadto twoja edycja jest niekompletna, ponieważ zmienne takie jak mAccel nie są nigdzie zadeklarowane. Powinieneś zacząć nowe pytanie, jeśli nadal masz problemy. To powiedziawszy, wygląda na to, że próbujesz "mAccel" wygładzoną wartość 'mAccelCurrent' w dość dziwny sposób. Zamiast tego sugeruję 'mAccel = mAccel * 0.9f + mAccelCurrent * 0.1f'. poza tym, myślę, że powinieneś zalogować mAccel i mAccelCurrent do pliku, zbadać wyniki i zdecydować, co z tym zrobić. – Stochastically