1

My application uses camera. To display the camera's preview the way the right way I must account for activity orientation relative to the physical device orientation. I. e. if the activity orientation is locked and never changes, I need not take any further steps - as the device rotates, preview image will rotate accordingly. However, imagine my activity is allowed to change orientation. You rotate the device - and preview - until you reach portrait mode (assuming it was landscape originally), at which point activity rotates to accommodate the new orientation. But preview image rotates with it, and now it's out of sync with the camera and surrounding reality. What I must do is determine activity orientation and rotate the image accordingly.

It seems that Display.getRotation() can be used for that. But apparently, it cannot: https://groups.google.com/forum/#!topic/android-developers/ij_0QbApKKc

The problem is that the point of origin is not fixed by Android API. Some tablets return rotation of 0 in normal orientation (landscape, volume buttons up), and some others (like my Nexus 7 2013) return 1.

How can I solve this problem?

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
  • Might as well update your questions title and the content as it's unclear what you want. The rotation or the orientation. – Simas Oct 23 '14 at 07:30
  • It is difficult to figure out what it is you're asking. But it sounds like you just need to know if you're activity is running in portrait or landscape mode. This is easily done by comparing the width/height of the screen. If height > width, then it's in portrait mode, otherwise it's in landscape mode. – Greg Miller Oct 29 '14 at 20:19
  • @GregMiller: I'm sorry, I did not realize my English is that bad. Don't know how else to state the question. No, you got it wrong, that's not what I mean. It's not my 1st year of Android development and I certainly wouldn't need to ask a new question for something that simple, let alone place a bounty. In short: I need exactly what `Display.getRotation()` does. No more, no less. Problem is that `Display.getRotation()` doesn't work, and the exact way it doesn't work is described in the question. – Violet Giraffe Oct 29 '14 at 21:47
  • 1
    Is it that you need to know the current orientation relative to the camera's default orientation? Here's a solved question that seemed to have the same problem: http://stackoverflow.com/questions/4553650/how-to-check-device-natural-default-orientation-on-android-i-e-get-landscape – Greg Miller Oct 29 '14 at 23:10

1 Answers1

1

You can determinate orientation using OrientationEventListener Something just like this

    mOrientationEventListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_NORMAL) {

            @Override
            public void onOrientationChanged(int orientation) {

                // determine our orientation based on sensor response

                Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();                                        

                if (display.getOrientation() == Surface.ROTATION_0) {   // landscape oriented devices
                    isLandscapeOriented = true;
                    if (orientation >= 315 || orientation < 45) {
                        if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {                         
                            mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
                        }
                    } else if (orientation < 315 && orientation >= 225) {
                        if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {
                            mOrientation = ORIENTATION_PORTRAIT_INVERTED;
                        }                       
                    } else if (orientation < 225 && orientation >= 135) {
                        if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
                            mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
                        }                       
                    } else if (orientation <135 && orientation > 45) { 
                        if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {
                            mOrientation = ORIENTATION_PORTRAIT_NORMAL;
                        }                       
                    }                       
                } else {  // portrait oriented devices

                    if (orientation >= 315 || orientation < 45) {
                        if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {                          
                            mOrientation = ORIENTATION_PORTRAIT_NORMAL;
                        }
                    } else if (orientation < 315 && orientation >= 225) {
                        if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {
                            mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
                        }                       
                    } else if (orientation < 225 && orientation >= 135) {
                        if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {
                            mOrientation = ORIENTATION_PORTRAIT_INVERTED;
                        }                       
                    } else if (orientation <135 && orientation > 45) { 
                        if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
                            mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
                        }                       
                    }
                }


            }
        };
    }
    if (mOrientationEventListener.canDetectOrientation()) {
        mOrientationEventListener.enable();
    }

Don`t forget to call mOrientationEventListener.disable();

EDIT:

    public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {

     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);

     int result;
     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
         result = (info.orientation + degrees) % 360;
         result = (360 - result) % 360;  // compensate the mirror
     } else {  // back-facing
       int rotation = activity.getWindowManager().getDefaultDisplay()
             .getRotation();
       int degrees = 0;
       switch (rotation) {
         case Surface.ROTATION_0: degrees = 0; break;
         case Surface.ROTATION_90: degrees = 90; break;
         case Surface.ROTATION_180: degrees = 180; break;
         case Surface.ROTATION_270: degrees = 270; break;
       }
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);
 }
Serhii Nadolynskyi
  • 5,473
  • 3
  • 21
  • 20
  • When should I call `disable`, and what will happen if I don't? – Violet Giraffe Oct 24 '14 at 13:30
  • Also, your code is incomplete. Where do I set this listener? Which sensor, how to init it? – Violet Giraffe Oct 24 '14 at 13:34
  • Actually you don`t need to set that listener anywere - mOrientationEventListener.enable() should be enough. You can put that in your activity. I am enable that in onCreate and disable in onDestroy. And not calling disable - is bad practice, because instance of mOrientationEventListener will occupy your memory resources till app will be closed. – Serhii Nadolynskyi Oct 24 '14 at 15:40
  • So, how the going? Any luck in implementation? Or you need some additional instructions? – Serhii Nadolynskyi Oct 27 '14 at 07:54
  • Just tried it. Unfortunately, that is absolutely not what I need. To reiterate what I already said in the question: I need to align the image from the camera with the screen. So all I need is to detect how the activity is oriented relative to the camera (i. e. the device's body). – Violet Giraffe Oct 27 '14 at 11:56
  • >>So all I need is to detect how the activity is oriented relative to the camera (i. e. the device's body). How about mOrientation value? Or if you used front facing camera - you need to consider 'mirror' effect - if you don`t - you will see in landscape mode flipped upside down preview. – Serhii Nadolynskyi Oct 27 '14 at 12:56
  • Updated my answer for 'mirror' effect considering. – Serhii Nadolynskyi Oct 27 '14 at 13:02
  • No. That's not it. For one, as stated in the question, `Display.getRotation()` does NOT work. If it did, that would be all I need and there won't be this question. – Violet Giraffe Oct 27 '14 at 13:47
  • Ok, maybe I am not understud your question from the beginnig. Let's start again. From the docs:"getRotation () Returns the rotation of the screen from its "natural" orientation." On your Nexus 7 2013 it returns 1 in landscape mode. It matches Surface.ROTATION_90. And I think it's mean that 'natural' orientation of that device is portrait. Ta-da) Maybe you should provide some code - "does NOT work" doesn`t give much information. – Serhii Nadolynskyi Oct 27 '14 at 19:20
  • I have 2 devices: Acer A500 and Nexus 7. Both are tablets. Their cameras are oriented _exactly the same_, but their "natural rotation" is different. So I can't use `getRotation ()` to adjust the camera image as the activity orientation changes. – Violet Giraffe Oct 27 '14 at 19:27
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/63726/discussion-between-serg0-and-violet-giraffe). – Serhii Nadolynskyi Oct 27 '14 at 20:16