How to check device natural (default) orientation on Android (i.e. get landscape for e.g., Motorola Charm or Flipout)
Asked Answered
N

14

47

I have an activity showing preview from camera, so it need to be set as landscape only. At the bottom (regardless of device rotation) I want to show a text view. I am using OrientationEventListener which gives device's orientation from its natural position. I can implement a solution which works well on portrait default devices but to make it work also on landscape default devices I need to be aware of running on such a device. Thus the question is how to check it?

Navigator answered 29/12, 2010 at 11:26 Comment(0)
N
-4

It can be done using Display.getOrientation() or Display.getRotation() (for API level >= 8).

Navigator answered 29/12, 2010 at 15:47 Comment(3)
How can this answer be selected as the best answer, it doesn't even answers the question. If you use Display.getRotation(), you only know the angle of rotation from the Natural orientation, that will be Surface.ROTATION_90 in portrait on Asus Transformer eeePad and the same result in landscape on Samsung Galaxy Nexus. So definitely not the good answer.Brim
@Climbatize, it does answer the question, but it just doesn't provide an example implementation or algorithm. You can just compare the orientation to the rotation to infer the natural orientation. However, I recommend against this because I've seen the two values go out of sync sometimes.Shrader
@Shrader oh, yeah, I see what you mean, I think I was too upset to notice this answer contained the base of an answer :)Brim
R
78

This method can help:--

public int getDeviceDefaultOrientation() {

    WindowManager windowManager =  (WindowManager) getSystemService(Context.WINDOW_SERVICE);

    Configuration config = getResources().getConfiguration();

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

    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)) {
      return Configuration.ORIENTATION_LANDSCAPE;
    } else { 
      return Configuration.ORIENTATION_PORTRAIT;
    }
}
Rothwell answered 27/3, 2012 at 11:4 Comment(6)
I would just add a test for 'Undefined' rotation before if test: if(rotation == Configuration.ORIENTATION_UNDEFINED) return Configuration.ORIENTATION_UNDEFINED;Becky
@Pascal: that seems wrong. rotation is not orientation. Did you mean config.orientation != Configuration.ORIENTATION_UNDEFINED?Maraca
@VioletGiraffe in new API, getOrientation() is deprecated and implemented as 'return getRotation()'. Things have obviously changed in new API... Thanks for the remark.Becky
I've found that sometimes this doesn't work correctly; orientation and getRotation are out of sync at some points in time.Shrader
To get the windowManager for the rotation you could also use: int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();Libradalibrarian
Adding to @Sam's comment, when user rotates phone, there is a short period of time where this method gives the opposite answer from the truth. Then it is correct again. TBD whether this problem is only on certain phones and/or versions of Android.Aforethought
R
12

Well, you can find out what current orientation is the way @Urboss said. You cannot get the layout (landscape/portrait) that way ofcourse, so you'll have to get the screen width/heigth to check if the current (be it changed or not, but you've checked that ;) ) position is landscape or portrait:

    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    wPix = dm.widthPixels;
    hPix = dm.heightPixels;

(so if the rotation is 0 and you get landscape with above metrix, your device is default landscape. If the rotation is 90 degrees and you're portrait, the default is also landscape, and so on)

Roughshod answered 14/1, 2011 at 10:2 Comment(0)
N
9

After hours and hours of trying to figure this out. It's not possible. However, the closest thing you can do is to set the orientation to "NOSENSOR"

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

What this will do is set your application to the natural orientation of the device. At this point you can get the height and width of the display using the DisplayMetrics class, and calculate if you are in landscape or portrait. After you then figure out if it's landscape or portrait, you can then do this

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_XXXXX);

Where XXXX is either LANDSCAPE or PORTRAIT.

The case where doing this may not work is if you have a slide out keyboard.

Nightclub answered 29/4, 2011 at 22:7 Comment(2)
It should be setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);Michal
@diyism, as far as I know, SCREEN_ORIENTATION_UNSPECIFIED allows the activity orientation to be overridden by the user enabling auto screen rotation or by the system USER_ROTATION setting value changing.Shrader
J
7

Thanks to diyism's excellent answer above, I also added the logic to check the actual orientation position (landscape right, portrait, landscape left, portrait flipped): enter image description here Here is the code:

@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
    //The coordinate-system is defined relative to the screen of the phone in its default orientation
    int orientation = 0;
    float roll=0;
    float pitch=0;
    switch (getWindowManager().getDefaultDisplay().getRotation())  {
        case Surface.ROTATION_0:
                 roll=event.values[2];
                 pitch=event.values[1];
            break;
            case Surface.ROTATION_90:
                 roll=event.values[1];
                 pitch=-event.values[2];
            break;
            case Surface.ROTATION_180:
                 roll=-event.values[2];
                 pitch=-event.values[1];
            break;
            case Surface.ROTATION_270:
                 roll=-event.values[1];
                 pitch=event.values[2];
            break;
           }

    if (pitch >= -45 && pitch < 45 && roll >= 45)
        orientation = 0;
    else if (pitch < -45 && roll >= -45 && roll < 45) 
        orientation = 1; 
    else if (pitch >= -45 && pitch < 45 && roll < -45) 
        orientation = 2;
    else if (pitch >= 45 && roll >= -45 && roll < 45 ) 
        orientation = 3;

    if (m_nOrientation != orientation) { //orientation changed event
        m_Inst.Debug(LOG_TAG,"onSensorChanged: orientation:" + orientation);
        m_nOrientation = orientation;
        // fire event for new notification, or update your interface here
    }
}

This code is also posted here: http://www.pocketmagic.net/?p=2847

Jessabell answered 24/7, 2012 at 11:14 Comment(0)
M
6

Here's my solution:

public class ActivityOrientationTest extends Activity {
private static final String TAG = "ActivityOrientationTest";
private int mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
private TextView mTextView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);        
    setContentView(R.layout.main);
    mTextView = (TextView)findViewById(R.id.text);
    setDefaultOrientation();        
}

private void setDefaultOrientation(){
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);

    Display display;         
    display = getWindow().getWindowManager().getDefaultDisplay();
    int rotation = display.getRotation();
    int width = 0;
    int height = 0;
    switch (rotation) {
    case Surface.ROTATION_0:
    case Surface.ROTATION_180:
        Log.i(TAG, "Rotation is: 0 or 180");
        width = display.getWidth();
        height = display.getHeight();
        break;
    case Surface.ROTATION_90:       
    case Surface.ROTATION_270:
        Log.i(TAG, "Rotation is: 90 or 270");
        width = display.getHeight();
        height = display.getWidth();
        break;
    default:
        break;
    }

    if(width > height){
        Log.i(TAG, "Natural Orientation is landscape");
        mTextView.setText("Natural Orientation is landscape");
        mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    } else {
        Log.i(TAG, "Natural Orientation is portrait");
        mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        mTextView.setText("Natural Orientation is portrait");
    } 

    setRequestedOrientation(mNaturalOrientation);
}

Display.getRotation() is only supported in API level 8 or higher so if you need to support older devices you'll need to call Display.getOrientation().

Markman answered 13/9, 2011 at 23:30 Comment(0)
G
3
public static boolean isDeviceDefaultOrientationLandscape(Activity a) {

    WindowManager windowManager = (WindowManager) a.getSystemService(Context.WINDOW_SERVICE);

    Configuration config = a.getResources().getConfiguration();

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

    boolean defaultLandsacpeAndIsInLandscape = (rotation == Surface.ROTATION_0 ||
            rotation == Surface.ROTATION_180) &&
            config.orientation == Configuration.ORIENTATION_LANDSCAPE;

    boolean defaultLandscapeAndIsInPortrait = (rotation == Surface.ROTATION_90 ||
            rotation == Surface.ROTATION_270) &&
            config.orientation == Configuration.ORIENTATION_PORTRAIT;

    return defaultLandsacpeAndIsInLandscape || defaultLandscapeAndIsInPortrait;
}
Guadalajara answered 4/8, 2015 at 9:59 Comment(0)
M
2

@Urboss, it can't. You need to know the default orientation of the device first, because both methods return the changes based on it (I mean, if the default is portrait, the result you are looking for will be 1 or ROTATE_90 -so it is landscape-, but, if the default is landscape, the result is 0).

And as far as I know, finding the default orientation of the device is not trivial :(

Anybody can throw some light in this topic?

Metaphor answered 14/1, 2011 at 9:36 Comment(1)
I wish I knew. I really want to be able to find the natural orientation of the device my app is running on. >=\Nightclub
M
1

My solution(tested at HTC desire and SamSung galaxy tab 10.1):

    private class compass_listener implements SensorEventListener
            {public void onAccuracyChanged(Sensor sensor, int accuracy) {}

             public void onSensorChanged(SensorEvent event)
                    {float roll=0;
                     float pitch=0;
                     switch (((Activity)context).getWindowManager().getDefaultDisplay().getRotation())
                            {case Surface.ROTATION_0:
                                  roll=event.values[2];
                                  pitch=event.values[1];
                             break;
                             case Surface.ROTATION_90:
                                  roll=event.values[1];
                                  pitch=-event.values[2];
                             break;
                             case Surface.ROTATION_180:
                                  roll=-event.values[2];
                                  pitch=-event.values[1];
                             break;
                             case Surface.ROTATION_270:
                                  roll=-event.values[1];
                                  pitch=event.values[2];
                             break;
                            }
                     JSONObject json=new JSONObject();
                     try
                         {json.put("roll", roll);
                          json.put("pitch", pitch);
                          json.put("azimuth", event.values[0]);
                         }
                     catch (JSONException e)
                           {throw new RuntimeException(e);
                           }
                     java_2_js(webview, "intent_compass_change", json);
                    }
            }
Michal answered 14/9, 2011 at 5:21 Comment(0)
G
1

You can define by using rotation and orientation. No need to use sensors or any listeners, just call isDefaultLandscape method whenever you wish.

private boolean isDefaultLandscape(final Context context)
{
    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    int rotation = display.getRotation();
    int orientation = context.getResources().getConfiguration().orientation;

    switch (rotation)
    {
        case Surface.ROTATION_180:
        case Surface.ROTATION_0:
        {
            return orientation == Configuration.ORIENTATION_LANDSCAPE;
        }
        default:
        {
            return orientation == Configuration.ORIENTATION_PORTRAIT;
        }
    }
}
Gillie answered 28/4, 2017 at 8:20 Comment(0)
I
0

For fellow Xamarin developers, here is a version of this check in C#:

var orientation = ContextHelper.Current.Resources.Configuration.Orientation;
if (orientation == Android.Content.Res.Orientation.Undefined)
{
    //unknown, you can provide special handling for this case
}

var isLandscape = false;
var rotation = windowManager.DefaultDisplay.Rotation;           

switch (rotation)
{
    case SurfaceOrientation.Rotation0:
    case SurfaceOrientation.Rotation180:
        isLandscape = orientation == Android.Content.Res.Orientation.Landscape;
        break;
    default:
        isLandscape = orientation == Android.Content.Res.Orientation.Portrait;
        break;
}
Installment answered 26/3, 2019 at 11:47 Comment(0)
F
0

Here's what I've been using:

 /**
     * returns the natural orientation of the device: Configuration.ORIENTATION_LANDSCAPE or Configuration.ORIENTATION_PORTRAIT .<br/>
     * The result should be consistent no matter the orientation of the device
     */
    public static int getScreenNaturalOrientation(@NonNull final Context context) {
        //based on : https://mcmap.net/q/36886/-how-to-check-device-natural-default-orientation-on-android-i-e-get-landscape-for-e-g-motorola-charm-or-flipout
        final WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        final Configuration config = context.getResources().getConfiguration();
        final int rotation = windowManager.getDefaultDisplay().getRotation();
        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))
            return Configuration.ORIENTATION_LANDSCAPE;
        else
            return Configuration.ORIENTATION_PORTRAIT;
    }

You can also get the natural resolution as such:

/**
 * returns the natural screen size (in pixels). The result should be consistent no matter the orientation of the device
 */
public static
@NonNull
Point getScreenNaturalSize(@NonNull final Context context) {
    if (sNaturalScreenSize != null)
        return sNaturalScreenSize;
    final int screenNaturalOrientation = getScreenNaturalOrientation(context);
    final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    final int currentOrientation = context.getResources().getConfiguration().orientation;
    if (currentOrientation == screenNaturalOrientation)
        return sNaturalScreenSize = new Point(displayMetrics.widthPixels, displayMetrics.heightPixels);
    //noinspection SuspiciousNameCombination
    return sNaturalScreenSize = new Point(displayMetrics.heightPixels, displayMetrics.widthPixels);
}
Feltie answered 10/6, 2020 at 7:5 Comment(0)
R
0

After some googling, I found a blog mentioned that while executing wm size command through adb shell, it will always return the unrotated "natural" screen resolution, and then the author hunted down to here:

        mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService(
                        Context.WINDOW_SERVICE));

and here:

                mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);

So, it seems that Android actually knows the initial/unrotated/"natural" screen size, but, it just doesn't want the app to know it? I'm confused...

Ramonramona answered 28/7, 2021 at 10:44 Comment(0)
U
-3

its very simple to solve this

int orient=this.getResources().getConfiguration().orientation;

if it return 1 or 2

1 is portrait 2 is landscape

Unsuccess answered 17/10, 2015 at 7:22 Comment(1)
No, that returns the CURRENT orientation. This question is about the DEFAULT or NATURAL orientation. The goal is to ALWAYS return PORTRAIT for a phone, LANDSCAPE for a tablet -- REGARDLESS of how the person rotates the device. (tested on Samsung Tab S 10). This information is needed in certain situations, to process the available values correctly. For instance, when doing low-level hysteresis algorithms on accelerometer output.Aforethought
N
-4

It can be done using Display.getOrientation() or Display.getRotation() (for API level >= 8).

Navigator answered 29/12, 2010 at 15:47 Comment(3)
How can this answer be selected as the best answer, it doesn't even answers the question. If you use Display.getRotation(), you only know the angle of rotation from the Natural orientation, that will be Surface.ROTATION_90 in portrait on Asus Transformer eeePad and the same result in landscape on Samsung Galaxy Nexus. So definitely not the good answer.Brim
@Climbatize, it does answer the question, but it just doesn't provide an example implementation or algorithm. You can just compare the orientation to the rotation to infer the natural orientation. However, I recommend against this because I've seen the two values go out of sync sometimes.Shrader
@Shrader oh, yeah, I see what you mean, I think I was too upset to notice this answer contained the base of an answer :)Brim

© 2022 - 2024 — McMap. All rights reserved.