Android: Temporarily disable orientation changes in an Activity

AndroidScreen OrientationAndroid Orientation

Android Problem Overview


My main activity has some code that makes some database changes that should not be interrupted. I'm doing the heavy lifting in another thread, and using a progress dialog which I set as non-cancellable. However, I noticed that if I rotate my phone it restarts the activity which is REALLY bad for the process that was running, and I get a Force Close.

What I want to do is programatically disable screen orientation changes until my process completes, at which time orientation changes are enabled.

Android Solutions


Solution 1 - Android

As explained by Chris in his self-answer, calling

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

and then

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

really works like charm... on real devices !

Don't think that it's broken when testing on the emulator, the ctrl+F11 shortcut ALWAYS change the screen orientation, without emulating sensors moves.

EDIT: this was not the best possible answer. As explained in the comments, there are issues with this method. The real answer is here.

Solution 2 - Android

None of the other answers did the trick perfectly for me, but here's what I found that does.

Lock orientation to current...

if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

When changing orientation should be allowed again, set back to default...

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

Solution 3 - Android

Here is a more complete and up to date solution that works for API 8+, works for reverse portrait and landscape, and works on a Galaxy tab where the "natural" orientation is landscape (call activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) to unlock the orientation):

@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
public static void lockActivityOrientation(Activity activity) {
	Display display = activity.getWindowManager().getDefaultDisplay();
	int rotation = display.getRotation();
	int height;
	int width;
	if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
		height = display.getHeight();
		width = display.getWidth();
	} else {
    	Point size = new Point();
    	display.getSize(size);
		height = size.y;
		width = size.x;
	}
	switch (rotation) {
    case Surface.ROTATION_90:
    	if (width > height)
    		activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    	else
    		activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        break;
    case Surface.ROTATION_180:
    	if (height > width)
    		activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
    	else
        	activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        break;          
    case Surface.ROTATION_270:
    	if (width > height)
    		activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
    	else
        	activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        break;
    default :
    	if (height > width)
    		activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    	else
    		activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
	}
}

Solution 4 - Android

In order to manage also the reverse orientation modes, I have used that code to fix the activity orientation:

int rotation = getWindowManager().getDefaultDisplay().getRotation();
	    	    	
	switch(rotation) {
	case Surface.ROTATION_180:
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
		break;
	case Surface.ROTATION_270:
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);    		
		break;
	case  Surface.ROTATION_0:
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		break;
	case Surface.ROTATION_90:
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		break;
	}

And to allow again the orientation:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

Solution 5 - Android

Use setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); for locking current orientation whether it be landscape or portrait.

Use setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); for unlocking orientation.

Solution 6 - Android

I found the answer. To do this, in an Activity you can call setRequestedOrientation(int) with one of the values specified here: http://developer.android.com/reference/android/R.attr.html#screenOrientation

Before I kicked off my thread I called setRequestedOrientation(OFF) (OFF = nosensor) and when the thread was done I called setRequestedOrientation(ON) (ON = sensor). Works like a charm.

Solution 7 - Android

Thanks all. I modified Pilot_51's solution, to make sure I restored to the previous state. I also threw in a change to support non-landscape and non-portrait screens (but haven't tested it on such a screen).

prevOrientation = getRequestedOrientation();
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}

Then to restore it

setRequestedOrientation(prevOrientation);

Solution 8 - Android

protected void setLockScreenOrientation(boolean lock) {
    if (Build.VERSION.SDK_INT >= 18) {
        setRequestedOrientation(lock?ActivityInfo.SCREEN_ORIENTATION_LOCKED:ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        return;
    }

    if (lock) {
        switch (getWindowManager().getDefaultDisplay().getRotation()) {
            case 0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; // value 1
            case 2: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; // value 9
            case 1: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; // value 0
            case 3: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; // value 8
        }
    } else
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); // value 10
}

Solution 9 - Android

Here is a solution which works every time and preserves current orientation (using Activity.Info.SCREEN_ORIENTATION_PORTRAIT sets to 0° for instance, but user can have a 180° orientation as current one).

// Scope: Activity

private void _lockOrientation() {
    if (super.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
    } else {
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
    }
}

private void _unlockOrientation() {
    super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

Solution 10 - Android

use ActivityInfo.SCREEN_ORIENTATION_USER if you want to rotate screen only if its enabled on device.

Solution 11 - Android

This works prefect for me. It solves problem with different "natural orientation" of tablet/phone ;)

int rotation = getWindowManager().getDefaultDisplay().getRotation();

        Configuration config = getResources().getConfiguration();
        int naturalOrientation;

        if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
                config.orientation == Configuration.ORIENTATION_LANDSCAPE)
                || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
                config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
            naturalOrientation = Configuration.ORIENTATION_LANDSCAPE;
        } else {
            naturalOrientation = Configuration.ORIENTATION_PORTRAIT;
        }

        // because getRotation() gives "rotation from natural orientation" of device (different on phone and tablet)
        // we need to update rotation variable if natural orienation isn't 0 (mainly tablets)
        if (naturalOrientation == Configuration.ORIENTATION_LANDSCAPE)
            rotation = ++rotation % 4;

        switch (rotation) {
            case Surface.ROTATION_0: //0
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                break;
            case Surface.ROTATION_90: //1
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                break;
            case Surface.ROTATION_180: //2
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
                break;
            case Surface.ROTATION_270: //3
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
                break;
        }
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }

Solution 12 - Android

I have come up with a solution which depends on the display rotation and then decides the orientation of the device. From knowing the orientation we can lock the orientation and release it later when needed. This solution also can determine if the device in reverse landscape mode.

private void lockOrientation(){
	switch (((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation()) {


        // Portrait
	    case Surface.ROTATION_0:
	    	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
	    	break;


        //Landscape		
		case Surface.ROTATION_90: 
	    	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
	        break;


        // Reversed landscape
	    case Surface.ROTATION_270:
	    	setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);		    	
	        break;
    }
}

Then later if we need to release the orientation we can call this method:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

Solution 13 - Android

I think this code is easier to read.

private void keepOrientation() {

    int orientation = getResources().getConfiguration().orientation;
    int rotation = getWindowManager().getDefaultDisplay().getRotation();

    switch (rotation) {
        case Surface.ROTATION_0:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
            break;
        case Surface.ROTATION_90:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
            break;
        case Surface.ROTATION_180:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            }
            break;
        default:
            if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
            }
    }
}

Solution 14 - Android

I have found a combination of existing rotation/orientation values are needed to cover the four possibilities; there's the portrait/landscape values and the natural orientation of the device. Let's say the devices' natural orientation will have a rotation value of 0 degrees when the screen is in it's "natural" portrait or landscape orientation. Similarly, there will be a rotation value of 90 degrees when it's in landscape or portrait (notice it's opposite of the orientation @ 0 degrees). So the rotation values that are not 0 or 90 degrees will imply "Reverse" orientation. Ok, here's some code:

public enum eScreenOrientation 
{
PORTRAIT (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT),
LANDSCAPE (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),
PORTRAIT_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT),
LANDSCAPE_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE),
UNSPECIFIED_ORIENTATION (ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

    public final int activityInfoValue;
	
    eScreenOrientation ( int orientation )
    {
	    activityInfoValue = orientation;
    }
}



public eScreenOrientation currentScreenOrientation ( )
{
	final int rotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();

	final int orientation = getResources().getConfiguration().orientation;
	switch ( orientation ) 
	{
	case Configuration.ORIENTATION_PORTRAIT:
		if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 )
			return eScreenOrientation.PORTRAIT;
		else
			return eScreenOrientation.PORTRAIT_REVERSE;
	case Configuration.ORIENTATION_LANDSCAPE:
		if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 )
			return eScreenOrientation.LANDSCAPE;
		else
			return eScreenOrientation.LANDSCAPE_REVERSE;
	default:
		return eScreenOrientation.UNSPECIFIED_ORIENTATION;
	}
}

public void lockScreenOrientation ( )
	throws UnsupportedDisplayException
{
	eScreenOrientation currentOrientation = currentScreenOrientation( );
	if ( currentOrientation == eScreenOrientation.UNSPECIFIED_ORIENTATION )
		throw new UnsupportedDisplayException("Unable to lock screen - unspecified orientation");
	else
		setRequestedOrientation( currentOrientation.activityInfoValue );
}

public void unlockScreenOrientation (  )
{
	setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED );
}

Solution 15 - Android

I didn't like most of the answers here, since in the unlock they set it to UNSPECIFIED as opposed to the previous state. ProjectJourneyman did take it into account, which was great, but I preferred the locking code by Roy. So, my recommendation would be a mix of the two:

private int prevOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;

private void unlockOrientation() {
    setRequestedOrientation(prevOrientation);
}

@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private void lockOrientation() {
    prevOrientation = getRequestedOrientation();
    Display display = getWindowManager().getDefaultDisplay();
    int rotation = display.getRotation();
    int height;
    int width;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) {
        height = display.getHeight();
        width = display.getWidth();
    } else {
        Point size = new Point();
        display.getSize(size);
        height = size.y;
        width = size.x;
    }
    switch (rotation) {
        case Surface.ROTATION_90:
            if (width > height)
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            else
                setRequestedOrientation(9/* reversePortait */);
            break;
        case Surface.ROTATION_180:
            if (height > width)
                setRequestedOrientation(9/* reversePortait */);
            else
                setRequestedOrientation(8/* reverseLandscape */);
            break;
        case Surface.ROTATION_270:
            if (width > height)
                setRequestedOrientation(8/* reverseLandscape */);
            else
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            break;
        default :
            if (height > width)
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            else
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

Solution 16 - Android

You can use

public void swapOrientaionLockState(){
    try{
        if (Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1) {
            Display defaultDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, defaultDisplay.getRotation());
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0);
        } else {
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 1);
        }

        Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, !orientationIsLocked() ? 1 : 0);

    } catch (Settings.SettingNotFoundException e){
        e.printStackTrace();
    }
}

public boolean orientationIsLocked(){
    if(canModifiSetting(mContext)){
        try {
            return Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0;
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
    }
    return false;
}

public static boolean canModifiSetting(Context context){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return Settings.System.canWrite(context);
    } else {
        return true;
    }
}

Solution 17 - Android

use that line of code

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  

in ur activity oncreate method

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChristopher PerryView Question on Stackoverflow
Solution 1 - AndroidKevin GaudinView Answer on Stackoverflow
Solution 2 - AndroidPilot_51View Answer on Stackoverflow
Solution 3 - AndroidRoyView Answer on Stackoverflow
Solution 4 - AndroidIvan BASARTView Answer on Stackoverflow
Solution 5 - AndroidSudhir SinhaView Answer on Stackoverflow
Solution 6 - AndroidChristopher PerryView Answer on Stackoverflow
Solution 7 - AndroidProjectJourneymanView Answer on Stackoverflow
Solution 8 - AndroidtdjprogView Answer on Stackoverflow
Solution 9 - AndroidAdrien CadetView Answer on Stackoverflow
Solution 10 - AndroidPawan MaheshwariView Answer on Stackoverflow
Solution 11 - AndroidNaxosView Answer on Stackoverflow
Solution 12 - AndroidMansour FahadView Answer on Stackoverflow
Solution 13 - Androidnor_miyaView Answer on Stackoverflow
Solution 14 - AndroidMagic Hands PellegrinView Answer on Stackoverflow
Solution 15 - AndroidGadzairView Answer on Stackoverflow
Solution 16 - Androidmoviehay0032View Answer on Stackoverflow
Solution 17 - AndroidZeeshan AkhterView Answer on Stackoverflow