Programmatically Locking Android Screen Orientation

by Eric Miles

On my latest project, we had some technical requirements to lock the screen in the current orientation while some background processing occurred.  Once the processing was completed, orientation is returned back to whatever the orientation was before it was locked.  This seemed pretty straight forward as there are several examples around the net on how to lock in portrait or landscape.  Locking on the existing orientation didn't seem that difficult, use the existing orientation value:

int orientation = getRequestedOrientation();
setRequestedOrientation(orientation);

This seems pretty straight forward, until you take a look at the javadocs (or in my case, have a defect arise).  We found our locking code was working when in portrait mode, however it was not working when in landscape and orientation changed to potrait.  By adding in some debug log messages, we found out when in landscape, user orientation was being returned.  Looking at the javadoc, user orientation is defined as:

The user's current preferred orientation.

This user value can come from system settings and could of any value, so we can not confidently code for the appropriate orientation.  I'm unsure if it's a defect in the platform or if it was designed this way, but locking the orientation on this value does not lock the current orientation.

The absolute best way to programmatically determine orientation is to use a combination of screen width, height, and rotation.  Rotation is defined with constant values of 0, 90, 180, and 270.  A phone's natural orientation is portrait, so its base rotation value for portrait is 0.  That means that landscape rotation could be 90 or 270 and with the phone completely flipped upside down rotation is 180.  A tablet's natural orientation is landscape, so it's base rotation value for landscape is 0.  That also means a tablet's rotation could be 90 or 270 for portrait, and 180 if it is landscape but flipped upside down.  This rotation value in combination of screen size (i.e. is x greater than y) gives us a true representation for orientation and allows us to truly lock the orientation correctly.  Keep in mind, you need to account for reverse orientation.

Display display = getWindowManager().getDefaultDisplay();
int rotation = display.getRotation();
 
Point size = new Point();
display.getSize(size);
 
int lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 
if (rotation == Surface.ROTATION_0
		|| rotation == Surface.ROTATION_180) {
	// if rotation is 0 or 180 and width is greater than height, we have
	// a tablet
	if (size.x > size.y) {
		if (rotation == Surface.ROTATION_0) {
			lock = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
		} else {
			lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
		}
	} else {
		// we have a phone
		if (rotation == Surface.ROTATION_0) {
			lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
		} else {
			lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
		}
	}
} else {
	// if rotation is 90 or 270 and width is greater than height, we
	// have a phone
	if (size.x > size.y) {
		if (rotation == Surface.ROTATION_90) {
			lock = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
		} else {
			lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
		}
	} else {
		// we have a tablet
		if (rotation == Surface.ROTATION_90) {
			lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
		} else {
			lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
		}
	}
}