Sensor.TYPE_ORIENTATION deprecated and should not be used.
Reading the orientation of the device also caused me a headache. Here is the base class that I use for actions that require device orientation:
public abstract class SensorActivity extends Activity implements SensorEventListener { private SensorManager sensorManager; private final float[] accelerometerValues = new float[3]; private final float[] R = new float[9]; private final float[] I = new float[9]; private final float[] orientation = new float[3]; private final float[] remappedR = new float[9]; private final List<HasOrientation> observers = new ArrayList<HasOrientation>(); private int x; private int y; protected SensorActivity() { this(SensorManager.AXIS_X, SensorManager.AXIS_Y); } protected SensorActivity(int x, int y) { setAxisMapping(x, y); } public void setAxisMapping(int x, int y) { this.x = x; this.y = y; } protected void register(HasOrientation hasOrientation) { observers.add(hasOrientation); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); } @Override protected void onResume() { super.onResume(); sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI); sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI); } @Override protected void onPause() { sensorManager.unregisterListener(this); super.onPause(); } public void onAccuracyChanged(Sensor sensor, int accuracy) { } public void onSensorChanged(SensorEvent event) { switch(event.sensor.getType()) { case Sensor.TYPE_ACCELEROMETER: System.arraycopy(event.values, 0, accelerometerValues, 0, accelerometerValues.length); break; case Sensor.TYPE_MAGNETIC_FIELD: if (SensorManager.getRotationMatrix(R, I, accelerometerValues, event.values)) { if (SensorManager.remapCoordinateSystem(R, x, y, remappedR)) { SensorManager.getOrientation(remappedR, orientation); for (HasOrientation observer : observers) { observer.onOrientation(Orientation.fromRadians(orientation)); } } } break; default: throw new IllegalArgumentException("unknown sensor type"); } } }
The orientation looks something like this:
public class Orientation { public float azimuth; public float pitch; public float roll; public Orientation() { } public Orientation(float azimuth, float pitch, float roll) { this.azimuth = azimuth; this.pitch = pitch; this.roll = roll; } public void setTo(Orientation o) { this.azimuth = o.azimuth; this.pitch = o.pitch; this.roll = o.roll; } public void normalize() { azimuth = Angle.normalize(azimuth); pitch = Angle.tilt(pitch); roll = Angle.tilt(roll); } public static Orientation fromRadians(float[] vec) { return new Orientation((float)Math.toDegrees(vec[0]), (float)Math.toDegrees(vec[1]), (float)Math.toDegrees(vec[2])); } @Override public String toString() { return "{a=" + azimuth + ", p=" + pitch + ", r=" + roll + "}"; } }
You need to call setAxisMapping() to get the orientation oriented in portrait or landscape mode. I just called it from the constructor, so I canβt tell you what happens when you call it while it is running. You may need to reset the matrix.