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?

Urboss
  • 1,255
  • 2
  • 10
  • 17

14 Answers14

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;
    }
}
Tommy Visic
  • 373
  • 2
  • 7
user1035292
  • 1,378
  • 12
  • 14
  • 6
    I would just add a test for 'Undefined' rotation before if test: if(rotation == Configuration.ORIENTATION_UNDEFINED) return Configuration.ORIENTATION_UNDEFINED; – Pascal Feb 25 '14 at 11:50
  • @Pascal: that seems wrong. rotation is not orientation. Did you mean `config.orientation != Configuration.ORIENTATION_UNDEFINED`? – Violet Giraffe Dec 25 '14 at 14:04
  • @VioletGiraffe in new API, getOrientation() is deprecated and implemented as 'return getRotation()'. Things have obviously changed in new API... Thanks for the remark. – Pascal Dec 26 '14 at 08:39
  • 2
    I've found that sometimes this doesn't work correctly; `orientation` and `getRotation` are out of sync at some points in time. – Sam Jan 22 '15 at 12:09
  • To get the windowManager for the rotation you could also use: `int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();` – Moritz Feb 19 '15 at 11:17
  • 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. – ToolmakerSteve Oct 22 '16 at 19:12
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)

Nanne
  • 64,065
  • 16
  • 119
  • 163
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.

Andi Jay
  • 5,882
  • 13
  • 51
  • 61
  • 2
    It should be setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); – diyism Sep 13 '11 at 07:52
  • @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. – Sam Jan 22 '15 at 12:11
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

radhoo
  • 2,877
  • 26
  • 27
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().

jesusF10
  • 554
  • 5
  • 4
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;
}
Indrek Kõue
  • 6,449
  • 8
  • 37
  • 69
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?

  • I wish I knew. I really want to be able to find the natural orientation of the device my app is running on. >=\ – Andi Jay Apr 28 '11 at 22:30
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;
        }
    }
}
Ayaz Alifov
  • 8,334
  • 4
  • 61
  • 56
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);
                    }
            }
diyism
  • 12,477
  • 5
  • 46
  • 46
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;
}
Martin Zikmund
  • 38,440
  • 7
  • 70
  • 91
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 : http://stackoverflow.com/a/9888357/878126
        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);
}
android developer
  • 114,585
  • 152
  • 739
  • 1,270
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...

Chris Chen
  • 121
  • 2
-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

Issac Balaji
  • 1,441
  • 1
  • 13
  • 25
  • 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. – ToolmakerSteve Oct 21 '16 at 17:27
-3

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

cottonBallPaws
  • 21,220
  • 37
  • 123
  • 171
Urboss
  • 1,255
  • 2
  • 10
  • 17
  • 16
    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. – Climbatize Mar 09 '12 at 10:22
  • @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. – Sam Jan 22 '15 at 12:13
  • @Sam oh, yeah, I see what you mean, I think I was too upset to notice this answer contained the base of an answer :) – Climbatize Jan 23 '15 at 13:09