Screen orientation lock

43,730

Solution 1

Here is my solution it works on phones and tablets in any Android SDK.

switch (getResources().getConfiguration().orientation){
        case Configuration.ORIENTATION_PORTRAIT:
            if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.FROYO){
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                int rotation = getWindowManager().getDefaultDisplay().getRotation();
                if(rotation == android.view.Surface.ROTATION_90|| rotation == android.view.Surface.ROTATION_180){
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
                } else {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                }
            }   
        break;

        case Configuration.ORIENTATION_LANDSCAPE:
            if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.FROYO){
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            } else {
                int rotation = getWindowManager().getDefaultDisplay().getRotation();
                if(rotation == android.view.Surface.ROTATION_0 || rotation == android.view.Surface.ROTATION_90){
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                } else {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
                }
            }
        break;
    }

Solution 2

I modified diyism's answers slightly to compensate for the fact that you can't use reverse_landscape and reverse_portrait modes before version 2.3

private static void disableRotation(Activity activity)
{       
    final int orientation = activity.getResources().getConfiguration().orientation;
    final int rotation = activity.getWindowManager().getDefaultDisplay().getOrientation();

    // Copied from Android docs, since we don't have these values in Froyo 2.2
    int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
    int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;

    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.FROYO)
    {
        SCREEN_ORIENTATION_REVERSE_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
        SCREEN_ORIENTATION_REVERSE_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    }

    if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90)
    {
        if (orientation == Configuration.ORIENTATION_PORTRAIT)
        {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
        else if (orientation == Configuration.ORIENTATION_LANDSCAPE)
        {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
    }
    else if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270) 
    {
        if (orientation == Configuration.ORIENTATION_PORTRAIT) 
        {
            activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        }
        else if (orientation == Configuration.ORIENTATION_LANDSCAPE) 
        {
            activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        }
    }
}

private static void enableRotation(Activity activity)
{
    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

Solution 3

for a temporarily screen lock you can easily use:

//developing for android tablets **<uses-sdk android:minSdkVersion="12" />**
//works perfectly... **WATCH OUT**: look portrait to reverse-portrait on api level 13 :)

currentActivity.setRequestedOrientation(currentActivity.getResources().getConfiguration().orientation);

//to re-enable sensor, just do:

currentActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

used it for a temp screen lock during showing dialog and doing important background work..

be sure that currentActivity is valid at the time you try to access it, otherwise it wont work :)

good luck :)

Solution 4

// Works on all devices. The other solution only works on 1/2 of the devices.
// Lock orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
lockOrientation(rotation, Surface.ROTATION_270);
// Ensure that the rotation hasn't changed
if (getWindowManager().getDefaultDisplay().getRotation() != rotation) {
    lockOrientation(rotation, Surface.ROTATION_90);
}
// ...
private void lockOrientation(int originalRotation, int naturalOppositeRotation) {
    int orientation = getResources().getConfiguration().orientation;
    if (orientation == Configuration.ORIENTATION_PORTRAIT) {
        // Are we reverse?
        if (originalRotation == Surface.ROTATION_0 || originalRotation == naturalOppositeRotation) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else {
            setReversePortrait();
        }
    } else {
        // Are we reverse?
        if (originalRotation == Surface.ROTATION_0 || originalRotation == naturalOppositeRotation) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        } else {
            setReverseLandscape();
        }
    }
}

@SuppressLint("InlinedApi") 
private void setReversePortrait() {
    if (Build.VERSION.SDK_INT >= 9) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
}

@SuppressLint("InlinedApi") 
private void setReverseLandscape() {
    if (Build.VERSION.SDK_INT >= 9) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

Solution 5

Use: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) because Orientation is determined by a physical orientation sensor: the display will rotate based on how the user moves the device. This allows any of the 4 possible rotations, regardless of what the device will normally do (for example some devices won't normally use 180 degree rotation). And your code should work on Xoom too ...

Share:
43,730
Michael Pardo
Author by

Michael Pardo

I'm an Android developer in Ann Arbor, MI.

Updated on July 15, 2020

Comments

  • Michael Pardo
    Michael Pardo almost 4 years

    Is there a reliable way to lock screen orientation on all Android devices? The code below works for my Nexus S and other phones, but for some reason ROTATION_90 corresponds to SCREEN_ORIENTATION_REVERSE_PORTRAIT on the Xoom.

    Is there any way to reliably map rotation to orientation?

    private void lockScreenOrientation() {
        if (!mScreenOrientationLocked) {
            final int orientation = getResources().getConfiguration().orientation;
            final int rotation = getWindowManager().getDefaultDisplay().getOrientation();
    
            if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
                if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                }
                else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                }
            }
            else if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270) {
                if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
                }
                else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
                }
            }
    
            mScreenOrientationLocked = true;
        }
    }
    
    private void unlockScreenOrientation() {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
        mScreenOrientationLocked = false;
    }
    

    EDIT: This code is meant to get the current orientation and lock it. The orientation is locked temporarily, and then released to the user.

  • Michael Pardo
    Michael Pardo almost 13 years
    I'm trying to lock the current orientation in code temporarily. This won't work because it's permanent. Read my code to see what I'm trying to do.
  • adam
    adam almost 13 years
    hehe, i just read the description at the top of your question which didn't really say you were looking for a programmatic reversible solution..
  • Juozas Kontvainis
    Juozas Kontvainis about 12 years
    It works perfectly only on some versions of android. On which ones did you test? Did you test on phones in both landscape and reverse landscape orientations?
  • cV2
    cV2 about 12 years
    hey, it seems that if device orientation is portrait, you use your lock, it locks it to reverse portrait on api level 13 (3.2, i think).. so code should be adapted there, im on it :) sry change, i wont change it this time...
  • SkolVikingsGuy
    SkolVikingsGuy almost 12 years
    This works for me. I have a Xoom and a Nexus 7 to test with. The Xoom has a "natural" orientation of landscape, so it's landscape orientation values is ROTATION_0. It's portrait position is ROTATION_270. The Nexus7 has a "natural" orientation of portrait, so it's portrait orientation value is ROTATION_0, and it's landscape orientation is ROTATION_90.
  • SkolVikingsGuy
    SkolVikingsGuy almost 12 years
    I think you should be comparing <= FROYO instead of just < FROYO. REVERSE values aren't available until GINGERBREAD I believe.
  • SkolVikingsGuy
    SkolVikingsGuy almost 12 years
    This code doesn't work for all devices. For instance, the Xoom has ROTATION_270 mapped to PORTRAIT, not REVERSE_PORTRAIT. The solution below does work for.
  • SkolVikingsGuy
    SkolVikingsGuy almost 12 years
    My great fear is that these values can change per device, so that there's no way to do this properly. Android is a mess in this regard. It's amazing that there's not a simple way to get the current orientation and then later set the device to that same orientation, without spending a day figuring out how to do it and then it possibly not working correctly anyway.
  • ateiob
    ateiob over 11 years
    @NeTeInStEiN Yup. As seen in this thread as well. +1 for being one of the few who observed this.
  • ateiob
    ateiob over 11 years
    +1 for demonstrating that no one should expect locked reverse orientations <= FROYO.
  • Rich
    Rich over 10 years
    I saw your comment above about the Kindle Fire HD. I'm having a similar issue right now where I've had two different solutions (basically the same logic) that work across all my phones and tablets except for the Kindle Fire HD. Writing in a special case based on android.os.Build values feels more hacky than I'm comfortable with. Have you figured out why the Fire HD is different, an elegant solution, and/or how much of Kindle's line of devices act the same? Would love to discuss. Thx
  • enl8enmentnow
    enl8enmentnow over 10 years
    @Rich, it's because the naturalOppositeRotation is different on some phones. Using the above code figures out what the default is for your phone by checking if the rotation has changed. I save the value of naturalOppositeRotation in user preferences once I figure it out the first time.
  • enl8enmentnow
    enl8enmentnow over 10 years
    @Rich, you missed the point of the inlined API... that's irrelevant to the solution. The REVERSE.. doesn't exist before 9.
  • Rich
    Rich over 10 years
    So, the genius in this is that immediately after calling setRequestedOrientation, getRotation returns the new value...I thought it would be an asynchronous process and not be immediately available. Very insightful and crazy that it's hidden way down the thread with only a single upvote (from me).
  • enl8enmentnow
    enl8enmentnow over 10 years
    @Rich, you got it. To be fair to the other posters this full solution was added months after the original question.
  • Eric Simonton
    Eric Simonton over 10 years
    I tried this kind of technique on a Kindle Fire HD 7", and it caused the screen to flip upside down then immediately back (from the two calls to setRequestedOrientation). See my hard-coded solution in my own answer. You could easily use isLandscape270() in this solution, too, if anyone else runs into the same problem.
  • PerracoLabs
    PerracoLabs about 10 years
    But some bad news, I've tested it on the galaxy S3 and found an unexpected behaviour. My app is set to work in landscape only. If I leave the app on then lock the phone (turn off screen), and then back into the phone, the app comes back as portrait. I debugged the code and seems that "getResources().getConfiguration().orientation" returns always portrait when coming back from a locked screen instead of the app's landscape orientation setting specified in the manifest.
  • Nantoka
    Nantoka over 8 years
    Just tested it with Android 6.0 on a Nexus9. Still works like a charm.