1

오리엔테이션과 가속도계 수치를 기반으로 운동 움직임을 추적하는 앱을 만들고 있습니다 (운동 움직임이 매우 느림). 제가 가진 것은 전략 운동입니다. 나는 운동 운동을위한 추상적 인 수업을 가지며 실제 운동은 실제 운동을 구현합니다. 문제는, 내 활동에서 onSensorChanged() 메소드의 다른 연습 문제를 추적하기 위해 스레드를 생성하고 있습니다. 이것은 많은 시간 호출 될 것이기 때문에, 나는 내 코드가 많은 쓰레드를 스폰할지 모른다. 그들은 쓰레기를 수집합니까?Android에서 onSensorChanged()의 스폰 스레드

코드 : 수천하지 않을 경우

public class WorkoutBuddy extends Activity implements SensorEventListener { 

    TextView t1, t2, t3, t4, t5, t6, t7; 
    SensorManager sensorManager;; 
    private Sensor sensorAccelerometer; 
    private Sensor sensorMagneticField; 
    private float[] valuesAccelerometer; 
    private float[] valuesMagneticField; 
    private float[] valuesOrientation; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.exercise_buddy); 

     sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); 
     sensorAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
     sensorMagneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 

     valuesAccelerometer = new float[3]; 
     valuesMagneticField = new float[3]; 
     valuesOrientation = new float[3]; 

     matrixR = new float[9]; 
     matrixI = new float[9]; 
     matrixValues = new float[3]; 

     //mediaPlayer = MediaPlayer.create(this, R.raw.first_position_confirmation); 
    } 

    @Override 
    protected void onPause() { 
     sensorManager.unregisterListener(this,sensorAccelerometer); 
     sensorManager.unregisterListener(this,sensorMagneticField); 
     super.onPause(); 
    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int accuracy) { 
     // TODO Auto-generated method stub 
    } 

    float[] orientation; 
    private float[] matrixR; 
    private float[] matrixI; 
    private float[] matrixValues; 

    @Override 
    public void onSensorChanged(SensorEvent event) { 


     if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 
      valuesAccelerometer = lowPass(event.values.clone(), valuesAccelerometer); 
     } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { 
      valuesMagneticField = lowPass(event.values.clone(), valuesMagneticField); 
     } 
     if (valuesAccelerometer != null && valuesMagneticField != null) { 
      SensorManager.getRotationMatrix(matrixR, matrixI, valuesAccelerometer, valuesMagneticField); 

      if(true){ 
       SensorManager.getOrientation(matrixR, matrixValues); 

       double azimuth = Math.toDegrees(matrixValues[0]); 
       double pitch = Math.toDegrees(matrixValues[1]); 
       double roll = Math.toDegrees(matrixValues[2]); 

       valuesOrientation[0]=(float) pitch; 
       valuesOrientation[1]=(float) roll; 
       valuesOrientation[0]=(float) azimuth; 


       Thread forExc1 = new Thread(new LeftShoulder(valuesAccelerometer, valuesOrientation, this)); 
       Thread forExc2 = new Thread(new RightShoulder(valuesAccelerometer, valuesOrientation, this)); 

       forExc1.run(); 
       forExc2.run(); 

      } 

     } 
    } 

    @Override 
    protected void onResume() { 
     sensorManager.registerListener(this,sensorAccelerometer,SensorManager.SENSOR_DELAY_NORMAL); 
     sensorManager.registerListener(this,sensorMagneticField,SensorManager.SENSOR_DELAY_NORMAL); 
     super.onResume(); 
    } 

    //Low pass filter used to smooth the sensor readings 
    protected float[] lowPass(float[] input, float[] output) { 
     float ALPHA = 0.25f; 
     if (output == null) return input;  
     for (int i=0; i<input.length; i++) { 
      output[i] = output[i] + ALPHA * (input[i] - output[i]); 
     } 
     return output; 
    } 


} 



package com.example.msapp2; 


public abstract class ExerciseMovement implements Runnable{ 
    protected float[] acc, ori; 
    protected boolean played = false; 

} 



package com.example.msapp2; 

import android.content.Context; 
import android.media.MediaPlayer; 

public class LeftShoulder extends ExerciseMovement { 

    MediaPlayer mediaPlayer; 
    public LeftShoulder(float[] accelerometer, float[] orientation, Context context){ 
     mediaPlayer = MediaPlayer.create(context, R.raw.first_position_confirmation); 
     acc = accelerometer; 
     //this.ori = orientation; 
    } 

    public void run(){ 
     if(acc[0]> -10 && acc[0] < -8.5 && !played){ 
      mediaPlayer.start(); 
      played = true; 
     } 
    } 


} 
+0

내가 어떤 안드로이드 수행 한 이후 오랜만하는 데 도움을하지만, 당신이 할 수 있습니다 'Executor' 클래스를 확인하십시오. 이 클래스는 수행 할 작업을 전달하도록 설계되었으며 스레드 풀 관리를 모두 담당합니다. 여기에 체크 아웃 할 수있는 문서가 있습니다. 그것에는 몇 가지 예가 있습니다. http://developer.android.com/reference/java/util/concurrent/Executor.html – DavidAndroidDev

+0

또한, @rupps answer의 관점에서, 이벤트의 타임 스탬프를 확인함으로써 생성을 끝낼 스레드의 양을 제어 할 수 있습니다 앱에서 의미가있는 경우 몇 초마다 작업을 생성 할 수 있습니다. – DavidAndroidDev

답변

2

그냥 OnSensorChanged을 무시하고 출력 Log.d 경우, 당신은 초당 번으로,이 수백라고 볼 수 있습니다.

난 당신에게 반대의 접근 방식을 제안 : 다른 수신 이벤트, 다음 onSensorChanged에서 같은 스레드를 공급 백그라운드에서 처리 할 하나 개의 스레드를 만듭니다.

스레드에서 이벤트 대기열의 종류를 구현하십시오. 끊임없이 수천 개의 이벤트가 도착할 것이라고 가정합니다.

뭔가 같은 :

 private class ShoulderMovementProcessorThread extends Thread { 

       ..... 

       // this will be called from the UI thread, just add event to the (synchronized) queue. 

       public void publish (int[] valuesAccelerometer, int[] valuesWhatever) { 

        add_event_to_queue(); 

       } 

       // this is the typical event loop where you read one from the queue, process it, then wait for the next 
       public void run() { 
        -> get event 
        -> process event 
        -> wait for next event 
       } 

     } 

     ShoulderMovementProcessorThread mShoulderProcessor=new ShoulderMovementProcessorThread(...); 

     @Override 
     public void onSensorChanged(SensorEvent event) { 
       decodeEvent (event); // fills up azimuth, roll, etc. 
       mShoulderProcessor.publish(valuesAccelerometer, valuesWhatever);   

     } 


     // decode an event 
     private void decodeEvent (SensorEvent event) { 

      if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 
       valuesAccelerometer = lowPass(event.values.clone(), valuesAccelerometer); 
      } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { 
       valuesMagneticField = lowPass(event.values.clone(), valuesMagneticField); 
      } 
      if (valuesAccelerometer != null && valuesMagneticField != null) { 
       SensorManager.getRotationMatrix(matrixR, matrixI, valuesAccelerometer, valuesMagneticField); 

       if(true){ 
        SensorManager.getOrientation(matrixR, matrixValues); 

        double azimuth = Math.toDegrees(matrixValues[0]); 
        double pitch = Math.toDegrees(matrixValues[1]); 
        double roll = Math.toDegrees(matrixValues[2]); 

        valuesOrientation[0]=(float) pitch; 
        valuesOrientation[1]=(float) roll; 
        valuesOrientation[0]=(float) azimuth; 

       } 

      } 
     } 
+0

예를 들어 주시겠습니까? 나는 당신이 말하려고했던 것을 완전히 이해하지 못했습니다. –

+0

스레드에 끊임없이 변화하는 값을 어떻게 전달할 수 있는지 모르겠습니다. –

+2

@ user3000837 :'LinkedBlockingQueue'를 사용하십시오. – CommonsWare

0

내가 최근에 비슷한 구현 :

public class DBWorkerThread implements Runnable 
{ 
    private SensorEnum sensorType; 
    private LinkedBlockingQueue<float[]> sensorData; 
    private DBService dbService; 

    public DBWorkerThread(SensorEnum type, DBService dbService) 
    { 
     this.sensorType = type; 
     this.dbService = dbService; 
     this.sensorData = new LinkedBlockingQueue<float[]>(); 
    } 

    /** 
    * Add data to queue 
    * @param values 
    */ 
    public void addDataToProcess(float[] values) 
    { 
     if (sensorData.size() < sensorData.remainingCapacity()) 
     { 
      try 
      { 
       this.sensorData.put(values); 
      } 
      catch (Exception ex) 
      { 
       LogService.log("Error adding queue: " + ex.getMessage()); 
      } 
      LogService.log("Added to queue. Size: " + sensorData.size()); 
     } 
    } 

    /** 
    * Processes queue of data 
    */ 
    @Override 
    public void run() 
    { 
     // Moves the current Thread into the background 
     android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); 

     while (sensorData.size() > 0) 
     { 
      try 
      { 
       float[] values = sensorData.take(); 
       storeData(values); 
      } 
      catch (Exception ex) 
      { 
       LogService.log("Error in queue: " + ex.getMessage()); 
      } 
     } 
    } 

    /** 
    * Store data to database 
    * @param values 
    */ 
    private void storeData(float[] values) 
    { 
     // store data 
    } 
} 

희망이