getDefaultDisplay().getRotation(); returns always same value - android

I´m trying to get the device orientation when taking a photo from a custom camera Activity.
Previously, I checked everywhere how to achieve it, and got no results to the solutions people suggest.
I´m using this line of code to retrieve the orientation with no results. It always returns 1. I´m using a Samsung Galaxy S III for developing, if it helps.
int rotation = getWindowManager().getDefaultDisplay().getRotation();
Log.d(TAG, "Taken rotation " + rotation);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
int orientation;
// if the device's natural orientation is portrait:
if ((rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180) && height > width ||
(rotation == Surface.ROTATION_90
|| rotation == Surface.ROTATION_270) && width > height) {
switch(rotation) {
case Surface.ROTATION_0:
orientation = 0;
break;
case Surface.ROTATION_90:
orientation = 90;
break;
case Surface.ROTATION_180:
orientation =180;
break;
case Surface.ROTATION_270:
orientation = 270;
break;
default:
Log.e(TAG, "Unknown screen orientation. Defaulting to " +
"portrait.");
orientation = 0;
break;
}

This is a guess based on what I know but I'm thinking Surface.ROTATION_90 is a constant integer name. Think of it like having this:
final int Surface.ROTATION_0 = 0;
final int Surface.ROTATION_90 = 1;
final int Surface.ROTATION_180 = 2;
final int Surface.ROTATION_270 = 3;
at the beginning of your program. When a precompiler sees one of these constants it automatically replaces it with the integer equivalent. When you initialize you're int rotation and set it to one of these the int holds the value that constant has been initialized at.
So, if you want to check Surface.Rotation directly you'll probably have to call getRotation() every time you check;
Something like:
Display display = getWindowManager().getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
//whatever you need to do here
}
etc.
or you can simply check for the integers these constants evaluate as.
int rotation = getWindowManager().getDefaultDisplay().getRotation;
if(rotation == 0)
{
//whatever you need to do here
}
etc.
Personally I'd go with the second option. Not having to call getRotation for every check might mean a small improvement in the runtime but its a good habit to minimize processor use whenever possible.

Related

How to set MediaRecorder orientation to landscape or portrait

How to set MediaRecorder orientation to landscape or portrait
I have been trying out the MediaRecorder class in Android
I had a look at this code
http://www.truiton.com/2015/05/capture-record-android-screen-using-mediaprojection-apis/
I want to set the orientation of the video being recorded to either portrait or Landscape
How can this be done
I Had a look at https://developer.android.com/reference/android/media/MediaRecorder.html#setOrientationHint(int)
It specifies to set the Rotation in Int, what values should we use for Landscape and Portrait Respectively
int: the angle to be rotated clockwise in degrees. The supported angles are 0, 90, 180, and 270 degrees.
You can take the refernce from the below for MediaRecorder.
You need to get the current camera orientation and then add the logic to set the orientation based on the front camera or back camera:
Below is for camera1API
Camera.CameraInfo camera_info = new Camera.CameraInfo()
int camera_orientation = camera_info.orientation;
Below is for camera2API
CameraCharacteristics characteristics;
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
characteristics = manager.getCameraCharacteristics(cameraIdS);
int camera_orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
Below is common for both camera1API and camera2API
The int camera_orientation of the camera image. The value is the angle that the camera image needs to be rotated clockwise so it shows correctly on the display in its natural orientation. It should be 0, 90, 180, or 270.
For example, suppose a device has a naturally tall screen. The back-facing camera sensor is mounted in landscape. You are looking at the screen. If the top side of the camera sensor is aligned with the right edge of the screen in natural orientation, the value should be 90. If the top side of a front-facing camera sensor is aligned with the right of the screen, the value should be 270.
private int getDeviceDefaultOrientation() {
WindowManager windowManager = (WindowManager)this.getContext().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;
}
}
Set orientation to landscape
int device_orientation = getDeviceDefaultOrientation();
int result;
if (device_orientation == Configuration.ORIENTATION_PORTRAIT) {
// should be equivalent to onOrientationChanged(270)
if (camera_controller.isFrontFacing()) {
result = (camera_orientation + 90) % 360;
} else {
result = (camera_orientation + 270) % 360;
}
} else {
// should be equivalent to onOrientationChanged(0)
result = camera_orientation;
}
Set orientation to portrait
int device_orientation = getDeviceDefaultOrientation();
int result;
if (device_orientation == Configuration.ORIENTATION_PORTRAIT) {
// should be equivalent to onOrientationChanged(0)
result = camera_orientation;
} else {
// should be equivalent to onOrientationChanged(90)
if (camera_controller.isFrontFacing()) {
result = (camera_orientation + 270) % 360;
} else {
result = (camera_orientation + 90) % 360;
}
}

Android Camera Rotation Generic

Im trying to rotate my camera when the device rotates, iv tried several methods, but none of them seem to work on all devices.
//This Works on my nexus 5 but not on my Samsung galaxy tab
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
if (mHolder.getSurface() == null)
{
return;
}
try
{
mCamera.stopPreview();
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("orientation", "landscape");
int rotation = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
int orientation = getContext().getResources().getConfiguration().orientation;
if (rotation == Surface.ROTATION_0) {
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mCamera.setDisplayOrientation(0);
} else {
mCamera.setDisplayOrientation(90);
}
}
else if (rotation == Surface.ROTATION_90) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
mCamera.setDisplayOrientation(270);
}
}
else if (rotation == Surface.ROTATION_180) {
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mCamera.setDisplayOrientation(180);
}
}
else if (rotation == Surface.ROTATION_270) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
mCamera.setDisplayOrientation(90);
}
}
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
catch (Exception e) {
}
}
// and i tried this, which is part of the documentation and it doesnt work on my nexus 5:
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 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;
}
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
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
Does someone have a working solution for all devices?
Although I'm not exactly sure what's your issue from the code you provided, here are few things one has to got right when using Camera API and image rotation on Android (the old one - on API <21)
1. You have to take in account the orientation of the image sensor.
The orientation of the sensor means its angle to the device native use-mode. (that's what actually does the google snippet you are using) For phones this is usually being set to portrait, on tablets to landscape.
Here is an excerpt from the documentation, it can make pain in head for a while, but that's just how things work.
For example, suppose a device has a naturally tall screen. The back-facing camera sensor is mounted in landscape. You are looking at the screen. If the top side of the camera sensor is aligned with the right edge of the screen in natural orientation, the value should be 90. If the top side of a front-facing camera sensor is aligned with the right of the screen, the value should be 270.
2. Frontfacing camera preview is being mirrored
If you use frontfacing camera, you have to take in account the implicit mirroring.
3. These rules are only meant for rotating the Camera preview
This is important. All this is only meant to allow you to display correctly rotated preview frames on the device screen. Once you take an actual picture, you have to rotate it once again to suit your needs. For front-facing images this might mean mirroring it yourself,...You can see the result of this "weirdness" among all apps on Android. Just take picture in hangouts and share it right away. On various phones you gotta get somewhat weirdly rotated image as the result.
4. OEMs does not adhere to specs all the time
All I can say, is that probably no solution will be hasslefree, we got some issues with some particular devices. (as usual on Android:)
5. Use the CWAC Camera library
We found this library to be a superior wrapper around the official Camera APIs. Solving practically all of the issues I did mention.

android setrequestorientation lock with current orientation calls on create in some devices

Hi and thanks in advance,
I am having a weird issue with screen lock orientation. The funny thing is this problem just happen to me in ONE device, a Samsung galaxy Tab. In the others tablets and smartphones does not react like this.
The thing is, imagine that you detect your orientation and lock it with this code:
public void lockScreenOrientation() {
System.out.println("A VER Q DEVUELVE ESTO: "+((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay().getRotation());
switch (((WindowManager) getSystemService(WINDOW_SERVICE))
.getDefaultDisplay().getRotation()) {
case Surface.ROTATION_90:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Surface.ROTATION_180:
setRequestedOrientation(9/* reversePortait */);
break;
case Surface.ROTATION_270:
setRequestedOrientation(8/* reverseLandscape */);
break;
default :
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
Suppostly, i just want to tell the device to keep the current orientation, but in that tablet it calls the onCreate !! why is that? why only that device? In the others works fine
And i do not want to override onConfigurationChanged because i need to call the code in on create, where the lock code is it....so it gets in a infinite loop........
Can i solve this? or it is a problem or issue of only this device?
best regards
I found the answer. It seems the orientation codes are not the same for tablet than to smartphone, i didn't know that.
The problem is that in the tablet the orientation i was trying to set, was wrong for him !! Like it is not the same for the smartphone than to the tablet
I found this other code, that perfectly did the trick for all devices :)
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
//Con esto pilla pantalla completa
screenheight = getWindowManager().getDefaultDisplay().getHeight();
screenwidth = getWindowManager().getDefaultDisplay().getWidth();
public void lockScreenOrientation() {
Display display = getWindowManager().getDefaultDisplay();
int rotation = display.getRotation();
Point size = new Point();
//display.getSize(size);
size.x=screenwidth;
size.y=screenheight;
int lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
if (rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180) {
// if rotation is 0 or 180 and width is greater than height, we have
// a tablet
if (size.x > size.y) {
if (rotation == Surface.ROTATION_0) {
lock = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
} else {
lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
}
} else {
// we have a phone
if (rotation == Surface.ROTATION_0) {
lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
} else {
lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
}
}
} else {
// if rotation is 90 or 270 and width is greater than height, we
// have a phone
if (size.x > size.y) {
if (rotation == Surface.ROTATION_90) {
lock = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
} else {
lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
}
} else {
// we have a tablet
if (rotation == Surface.ROTATION_90) {
lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
} else {
lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
}
}
}
setRequestedOrientation(lock);
}
When orientation is changed the OS destroys the activity and rebuilds it.. that is why onCreate is called. You could just set the activity in your manifest to only allow one orientation:
<activity
android:name=".YourActivity"
android:label="#string/app_name"
android:screenOrientation="portrait" >

Android camera rotation for portrait mode pictures

I'm trying to make a custom camera app. I'm taking pictures from the front facing camera without preview, but the resulting images are rotated according to the front camera orientation.
I searched through a lot of post here at stack, also the one described here in the android docs.
This is the solution that I came up with:
private void prepareCamera(Activity a){
//Rotation
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT,info);
int rotation = a.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
Log.d("TEST","rotation: "+rotation);
switch(rotation){
case Surface.ROTATION_0: degrees = 0; break; //Natural orientation
case Surface.ROTATION_90: degrees = 90; break; //Landscape left
case Surface.ROTATION_180: degrees = 180; break; //Upside down
case Surface.ROTATION_270: degrees = 270; break; //Landscape right
}
Log.d("TEST","degrees: "+degrees);
int result = (info.orientation + degrees) % 360;
Log.d("TEST","result: "+result);
result = (360 - result) % 360; //Compensate the mirror
Log.d("TEST","result: "+result);
//camera.setDisplayOrientation(result);
//Parameters
Camera.Parameters params = camera.getParameters();
params.setRotation(result);
params.setJpegQuality(100);
camera.setParameters(params);
//Preview
SurfaceView view = new SurfaceView(context);
try{
camera.setPreviewDisplay(view.getHolder());
}catch(IOException e){
throw new RuntimeException(e);
}
camera.startPreview();
}
It works, but I have two problems
1) I have the line, wich I took from the android docs, that "compensates the mirror". If I don't delete that line the pictures are well rotated according to the camera orientation, but they are overpassed by 180º. If I delete it the pictures are fine. I want to understand the why, if someone can please explain me.
I think its because that example code that I took from the docs its made for the SurfaceView, and it calls setDisplayOrientation(result);, when I'm using the results in .setRotation(result);. Maybe it has something to do with it?
2) When I'm testing I can rotate my phone to all directions but Upside down and get the pictures well rotated. But when I put the phone upside down, they are rotate 90, but upside down. As they were processed like Natural orientation. Maybe android wont track upside down rotation? If so, why would they with a case in the example provided by them.
Please look at setRotation() sample:
public void onOrientationChanged(int orientation) {
if (orientation == ORIENTATION_UNKNOWN) return;
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
orientation = (orientation + 45) / 90 * 90;
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - orientation + 360) % 360;
} else { // back-facing camera
rotation = (info.orientation + orientation) % 360;
}
mParameters.setRotation(rotation);
}
Display.getRotation(), unlike orientation sensor, is limited to orientations that your current Activity supports. On some devices, the portrait upside-down orientation is not supported by system.

Android: Temporarily disable orientation changes in an Activity

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.
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.
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);
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);
}
}
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.
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);
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.
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);
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
}
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);
}
use ActivityInfo.SCREEN_ORIENTATION_USER if you want to rotate screen only if its enabled on device.
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);
}
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);
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);
}
}
}
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 );
}
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);
}
}
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;
}
}
use that line of code
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
in ur activity oncreate method

Categories

Resources