Orientation Sensor Tips in Android

Orientation Sensor Tips in Android

I went through some pretty frustrating times recently trying to detect the physical orientation of the mobile device in Android recently so I figure I'll share my experience and what I learned here to hopefully prevent some pain for others out there.

Android has sensors to handle everything from acceleration to tricorder readings and all of them are managed via the SensorManager class. In order to detect changes to any sensor's reading you need to register a SensorListener with the manager.

First, I recommend creating your SensorListener inside your activity.

private final SensorListener sl = new SensorListener() {
	public void onSensorChanged(int sensor, float[] values) {

	public void onAccuracyChanged(int sensor, int accuracy) {

Next you'll want to find the Android SensorManager and register your SensorListener to listen for SENSOR_ORIENTATION events. It's best to put this code in your onCreate function of your Activity.

// Locate the SensorManager using Activity.getSystemService
SensorManager sm;
sm = (SensorManager) getSystemService(SENSOR_SERVICE);

// Register your SensorListener
sm.registerListener(sl, SensorManager.SENSOR_ORIENTATION SensorManager.SENSOR_DELAY_NORMAL);

Now your listener will be catching orientation events from the SensorManager. As the orientation changes the onSensorChanged method of your listener will be repeatedly called. The first parameter of the method should match the SensorManager.SENSOR_ORIENTATION value, assuming you didn't register it to listen to any other sensors. The second parameter will contain a float array of 3 values; Azimuth, Pitch, and Roll respectively.

Azimuth is used to detect your compass direction, where 0 = North, 90 = East, etc.. Pitch is used to track your devices side to side orientation, where vertical is around 0, tilted so the left side is on top is around 90, and tilted so the right side is on top is around -90. The documentation for pitch says the values range between -180 and 180, however when I tested this with my G1 device I found the values would not go beyond +/-90. As the device is tilted upside down the values would return back to 0 instead of +/- 180. This would make detecting whether the device is being held upside down or not rather difficult. I have not found a solution for this yet. The final value in the float array, roll, represents the degree to which the device is tilted back and forth.

I was only concerned with the side to side Orientation of the device, so I monitored only the pitch value like below and was able to easily track the device orientation.

float pitch = values[2];
if (pitch <= 45 && pitch >= -45) {
	// mostly vertical
} else if (pitch < -45) {
	// mostly right side up
} else if (pitch > 45) {
	// mostly left side up

The primary source of my previously mentioned frustration was from a class I first attempted to use called OrientationListener which extends the SensorListener class. From the name and the documentation you might think this would be the ideal class to use for listening to orientation changes, but it isn't, at least as far as I can tell. When registered in the same manner above the class will call back on it's onOrientationChanged funciton instead. The documentation says that values passed to this method represent the degrees of orientation of the device between 0 and 359 however in testing with my G1 I found the values to be completely useless and incorrect. Perhaps my G1 isn't functioning properly (although the above method using the SensorListener works just fine) or more likely I'm just implementing the OrientationListener incorrectly. I don't know because I haven't taken a look at the source code behind it yet. Perhaps this class needs to be depricated though, regardless, I'd recommend steering clear of it until some more appropriate examples of using it surface.



Oh Google, you think you're being all clever, don't you?

Oh Google, you think you're being all clever, don't you?