Search code examples
androidandroid-sensors

Getting Phone Angles


Right now I'm trying to get rotation of the phone. I've managed to write the code, that does this, but unfortunately it's giving values only on button click. How can I make TextView update every time values change? In other words - is there any EventListener for this? If yes, how to implement it?

public class MainActivity extends Activity {

SensorManager _sensorManager;

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

    SensorManager sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);        

    final float[] mValuesMagnet      = new float[3];
    final float[] mValuesAccel       = new float[3];
    final float[] mValuesOrientation = new float[3];
    final float[] mRotationMatrix    = new float[9];

    final Button btn_valider = (Button) findViewById(R.id.btn1);
    final TextView txt1 = (TextView) findViewById(R.id.textView1);
    final SensorEventListener mEventListener = new SensorEventListener() {
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }

        public void onSensorChanged(SensorEvent event) {
            // Handle the events for which we registered
            switch (event.sensor.getType()) {
                case Sensor.TYPE_ACCELEROMETER:
                    System.arraycopy(event.values, 0, mValuesAccel, 0, 3);
                    break;

                case Sensor.TYPE_MAGNETIC_FIELD:
                    System.arraycopy(event.values, 0, mValuesMagnet, 0, 3);
                    break;
            }
        };
    };

    // You have set the event lisetner up, now just need to register this with the
    // sensor manager along with the sensor wanted.
    setListners(sensorManager, mEventListener);

    btn_valider.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View view)
        {
            SensorManager.getRotationMatrix(mRotationMatrix, null, mValuesAccel, mValuesMagnet);
            SensorManager.getOrientation(mRotationMatrix, mValuesOrientation);
            final CharSequence test;
            float XAxis = (float) (mValuesOrientation[0] * 180/Math.PI);
            float YAxis = (float) (mValuesOrientation[1] * 180/Math.PI);
            float ZAxis = (float) (mValuesOrientation[2] * 180/Math.PI);
            test = "results: " + XAxis +" "+ YAxis+ " "+ ZAxis;
            txt1.setText(test);
        }
    });

}

// Register the event listener and sensor type.
public void setListners(SensorManager sensorManager, SensorEventListener mEventListener)
{
    sensorManager.registerListener(mEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), 
            SensorManager.SENSOR_DELAY_NORMAL);
        sensorManager.registerListener(mEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), 
                SensorManager.SENSOR_DELAY_NORMAL);

    }
}

Solution

  • Move the orientation calculation part in a separate method:

    private void calculateOrientation(){
          SensorManager.getRotationMatrix(mRotationMatrix, null, mValuesAccel, mValuesMagnet);
          SensorManager.getOrientation(mRotationMatrix, mValuesOrientation);
          final CharSequence test;
          float XAxis = (float) (mValuesOrientation[0] * 180/Math.PI);
          float YAxis = (float) (mValuesOrientation[1] * 180/Math.PI);
          float ZAxis = (float) (mValuesOrientation[2] * 180/Math.PI);
          test = "results: " + XAxis +" "+ YAxis+ " "+ ZAxis;
          txt1.setText(test);
    }
    

    Notice that you are already updating the value of the TextView by calling "txt1.setText(test);" after calculating the orientation. So, now you have to just make sure that this orientation calculation method is called every time the sensor data is changed.

    So then, just call this method from inside of the onSensorChanges() method:

    public void onSensorChanged(SensorEvent event) {
          // Handle the events for which we registered
          switch (event.sensor.getType()) {
             case Sensor.TYPE_ACCELEROMETER:
                System.arraycopy(event.values, 0, mValuesAccel, 0, 3);
                break;
    
             case Sensor.TYPE_MAGNETIC_FIELD:
                 System.arraycopy(event.values, 0, mValuesMagnet, 0, 3);
                 break;
          }
    
          //Call the orientation calculation method
          calculateOrientation();
     };
    

    This should update your TextView every time you have new sensor data available.