Android screen orientation to sensor - android

I want to force the screen orientation to landscape on button click by setting
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
It works fine. Now I want the application to follow the sensor so that orientation is brought back to portrait when tilted back to portrait. I know this is possible by setting setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); but don't know where to set it. If the orientation is forced to landscape, orientation will remain in landscape no matter you tilt in any direction. Can anyone specify how to reset the orientation flag?

Current YouTube app does what you are asking for.
I've dealt with same kind of problem in my application for video playback. If user forces orientation to landscape when he/she was in portrait, initialise OrientationEventListener which notifies you on device orientation from SensorManager which ranges from 0 to 360. Watch if device tilts to landscape orientation range which would be around (orientation >= 60 && orientation <= 120) || (orientation >= 240 && orientation <= 300) and save this state to a enum or a flag and then if device goes back to Portrait orientation range (orientation <= 40 || orientation >= 320), check the enum/flag and call setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); , reset the flag/enum and disable the sensor until user force orientation again.
Here is the demo code:
private enum SensorStateChangeActions {
WATCH_FOR_LANDSCAPE_CHANGES, SWITCH_FROM_LANDSCAPE_TO_STANDARD, WATCH_FOR_POTRAIT_CHANGES, SWITCH_FROM_POTRAIT_TO_STANDARD;
}
private SensorStateChangeActions mSensorStateChanges;
public void goFullScreen() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
mSensorStateChanges = SensorStateChangeActions.WATCH_FOR_LANDSCAPE_CHANGES;
if (null == sensorEvent)
initialiseSensor(true);
else
sensorEvent.enable();
}
public void shrinkToPotraitMode() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mSensorStateChanges = SensorStateChangeActions.WATCH_FOR_POTRAIT_CHANGES;
if (null == sensorEvent)
initialiseSensor(true);
else
sensorEvent.enable();
}
/**
* Initialises system sensor to detect device orientation for player changes.
* Don't enable sensor until playback starts on player
*
* #param enable if set, sensor will be enabled.
*/
private void initialiseSensor(boolean enable) {
sensorEvent = new OrientationEventListener(this,
SensorManager.SENSOR_DELAY_NORMAL) {
#Override
public void onOrientationChanged(int orientation) {
/*
* This logic is useful when user explicitly changes orientation using player controls, in which case orientation changes gives no callbacks.
* we use sensor angle to anticipate orientation and make changes accordingly.
*/
if (null != mSensorStateChanges
&& mSensorStateChanges == SensorStateChangeActions.WATCH_FOR_LANDSCAPE_CHANGES
&& ((orientation >= 60 && orientation <= 120) || (orientation >= 240 && orientation <= 300))) {
mSensorStateChanges = SensorStateChangeActions.SWITCH_FROM_LANDSCAPE_TO_STANDARD;
} else if (null != mSensorStateChanges
&& mSensorStateChanges == SensorStateChangeActions.SWITCH_FROM_LANDSCAPE_TO_STANDARD
&& (orientation <= 40 || orientation >= 320)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
mSensorStateChanges = null;
sensorEvent.disable();
} else if (null != mSensorStateChanges
&& mSensorStateChanges == SensorStateChangeActions.WATCH_FOR_POTRAIT_CHANGES
&& ((orientation >= 300 && orientation <= 359) || (orientation >= 0 && orientation <= 45))) {
mSensorStateChanges = SensorStateChangeActions.SWITCH_FROM_POTRAIT_TO_STANDARD;
} else if (null != mSensorStateChanges
&& mSensorStateChanges == SensorStateChangeActions.SWITCH_FROM_POTRAIT_TO_STANDARD
&& ((orientation <= 300 && orientation >= 240) || (orientation <= 130 && orientation >= 60))) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
mSensorStateChanges = null;
sensorEvent.disable();
}
}
};
if (enable)
sensorEvent.enable();
}
This worked similar to YouTube functionality, hope this helps.

I think here you should use setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)

It depends on when you want the sensor to detect rotation again.
Personally in an app I'm developping I have one specific activity where I need to be in portrait mode, so I use setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); in the onResume() of this activity and setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); in onPause() and it works just fine, when I enter the activity it sets to portrait if it's not and doesn't allow to change and on exitting the sensor works again...
Where are you trying to enable and disable the sensor?

Related

How to to find if device orientation is same as screen orientration

With
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
I can find the orientation of my layout. Now I want to lock my layout in some orientation e.g setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); and to find real phone orientation (layout is set to portrait, but user for some reason holds his device in landscape)
You have 2 options.
Use config changes:
Manifiest
<activity android:name=".HelloAndroid"
android:label="#string/app_name"
android:configChanges="orientation">
In your code
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
// TODO
}
You have to override this method.
Use an OrientationEventListener, which has a method called onOrientationChanged.
Here is a good Handling Runtime Changes tutorial.
EDIT:
Try this:
if (this.getWindow().getWindowManager().getDefaultDisplay()
.getOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
// portrait mode
} else if (this.getWindow().getWindowManager().getDefaultDisplay()
.getOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
// landscape
}
I have tested this way and it works for me.

Orientation Issue in Andengine Live Wallpaper

I have a live wallpaper in the market that runs very well for potrait mode, but as soon as its in landscape.. it looks stretched and bad. I have developed the wallpaper in andengine. I looked through the web to figure out that i need to implement onConfigurationChanged() method to take care of orientation changes. I used the solution proposed here :-
http://www.andengine.org/forums/live-wallpaper-extension/orentation-problem-landscape-portrait-t10669.html
Following is my onConfigurationChanged() method
#Override
public void onConfigurationChanged(Configuration newConfig) {
if (MODE == 0) {
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
mMainScene.setScale(1);
mMainScene.setPosition(0, 0);
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
mMainScene.setScaleY(1.5f);
mMainScene.setScaleX(0.5f);
mMainScene.setPosition(260, -500);
}
} else if (MODE == 1) {
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
mMainScene.setScaleY(0.5f);
mMainScene.setScaleX(1.5f);
mMainScene.setPosition(-500, 250);
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
mMainScene.setScale(1);
mMainScene.setPosition(0, 0);
}
}
}
The problem is that now when i see my wallpaper in preview mode, my mMainScene gets shifted to the right by 260 pixels as i have specified in my onConfigurationChanged() method. I think this problem can be solved if i can detect when my wallpaper is in preview mode but i can't seem to find out how to? I did try BaseWallpaperGLEngine.isPreview() method but it gives me a nullpointer exception. Can someone help me?
you can handle orientation change more properly, and avoid problems in preview mode. Look at this answer: AndEngine portrait distortion with RotationModifier

What gets called with sensorLandscape

I have an application that I only want to run in landscape mode (e.g. landscape or reverse landscape) so I am using sensorLandscape in the manifest.
My problem is here:
I also have a video recorder working (eg using the camera). Now I set the display orientation when i prepare the camera, but the problem is that if I change orientation that change stays (preview is upside down). When using sensor landscape how do I know when the UI is changed. I have tried using onConfigurationCanged() but unfortunately I need to have the app run on both pre honeycomb devices (mainly gingerbread) and post honeycomb devices (jelly bean).
Since in order to properly have onConfigurationChanged called i need to set target api to like 8, but sensor landscape is only available 9+. I need to set it to 8 because in the older api's you need to add screenSize to your "configChanges" otherwise it will not be called. So these calls have alot of incompatabilities between eachother.
Now that the background is done and you guys know what I have tried already. My question is
How can I find out when my orientation changes (callback, or something else) so that I can change my camera display orientation?
Thank you in advance.
I have figured out how to get this done. It is a round about way but here it is:
Set up a sensor manager and an oreitnation senosr
public class ActivityRecordVideo extends ActivityBase implements SensorEventListener
{
private SensorManager mSensorManager;
private Sensor mOrientation;
#Override
public void onCreate(Bundle savedInstanceState)
{
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
public void onSensorChanged(SensorEvent event) {
int rotation = getWindowManager().getDefaultDisplay().getRotation();
if(camId != -1 && currentDisplayRotation != rotation)
{
if(!isRecording)
setCameraOrientation(camId, cameraRecorder);
}
}
I also set the listeners in onResume() and remove them in onPause().
This allows for a camera orientation to flip with everything else (e.g. when in reverse landscape all views are in reverse landscape along with the camera preview)
Also decided to show setCameraOrientation code, it is a stipped down version of the android developers code
private void setCameraOrientation(int camId, Camera camera)
{
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(camId, info);
currentDisplayRotation = getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch(currentDisplayRotation)
{
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;
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; //compensate for mirror effect
if(Build.VERSION.SDK_INT < 14)
camera.stopPreview();
camera.setDisplayOrientation(result);
if(Build.VERSION.SDK_INT < 14)
camera.startPreview();
}
Hopefully this will help others

Android App How to rotation screen orientation temporarily

Is there any way to temporarily stop rotating the screen, perform a restore operation?
Request can not be turned off gravity sensor, it only prohibits the rotating screen.
To disable the orientation change you need to tell Android that you want to handle it by yourself.
To do so, add the following to your activity in the mainfest.xml:
android:configChanges="orientation"
Now override the following in the Activity:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
If you don't load a new layout here you will just keep the orientation.
Further details you can find here: http://developer.android.com/guide/topics/resources/runtime-changes.html

Detecting the screen orientation in android

I am implementing a camera in android. I have kept the activity as landscape in the manifest.
Since i have given the orientation as fixed, i am not able to get orientation by display. it always gives as LandScape. But i want to know when my device is held in portrait or vertical position. I do not want the screen orientation. Can any one suggest a good way to detect device orientation.
Thanks all
I think you will have to listen to the accelerometer sensor updates and parse them to determine when the orientation changes. there is some examples of listening to the sensors here: http://www.anddev.org/accessing_the_accelerometer-t499.html and here http://mobilestrategist.blogspot.com/2010/01/android-accelerometer-and-orientation.html
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
// Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
// Checks whether a hardware keyboard is available
if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
// Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();
} else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
// Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show();
}
}
To detect screen orientation you can use the following code in your activity
#Override
public void onConfigurationChanged(Configuration newConfig)
{ super.onConfigurationChanged(newConfig);
}
Thanks
Deepak
Try this:
First implement SensorEventListener and get the RotationSensor
sensorManager = (SensorManager)getActivity().getSystemService(Context.SENSOR_SERVICE);
rotationSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
sensorManager.registerListener(this, rotationSensor, SENSOR_INTERVAL);
int FROM_RADS_TO_DEGS = -57;
Then you can detect the angle of the device like this:
#Override
public void onSensorChanged(SensorEvent event) {
if(event.sensor == rotationSensor) {
if (event.values.length > 4) {
float[] truncatedRotationVector = new float[4];
System.arraycopy(event.values, 0, truncatedRotationVector, 0, 4);
updateRotation(truncatedRotationVector);
} else {
updateRotation(event.values);
}
}
}
private void updateRotation(float[] vectors) {
float[] rotationMatrix = new float[9];
SensorManager.getRotationMatrixFromVector(rotationMatrix, vectors);
int worldAxisX = SensorManager.AXIS_X;
int worldAxisZ = SensorManager.AXIS_Z;
float[] adjustedRotationMatrix = new float[9];
SensorManager.remapCoordinateSystem(rotationMatrix, worldAxisX, worldAxisZ, adjustedRotationMatrix);
float[] orientation = new float[3];
SensorManager.getOrientation(adjustedRotationMatrix, orientation);
float pitch = orientation[1] * FROM_RADS_TO_DEGS;
if(pitch < -45 && pitch > -135) {
// if device is laid flat on a surface, we don't want to change the orientation
return;
}
float roll = Math.abs(orientation[2] * FROM_RADS_TO_DEGS);
if((roll > 45 && roll < 135)) {
// The device is closer to landscape orientation. Enable fullscreen
if(!player.isFullScreen()) {
if(getActivity() != null) {
player.setFullScreenOn();
}
}
}
else {
// The device is closer to portrait orientation. Disable fullscreen
if(player.isFullScreen()) {
if(getActivity() != null) {
player.setFullScreenOff();
}
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do nothing
}
This got the original code from a tutorial, but it was a while ago, so I cant remember where the tutorial was. This version is heavily customised to my requirements, but if anyone recognises it from the original, please drop in the link.
I used this code to detect when a video player should go fullscreen inside a ViewPage that I didn't want to allow landscape orientation on. It works well except for one thing:
It uses RotationSensor hardware, and not all Android devices have a RotationSensor. If anyone knows of a way to do it using some hardware that is included on all devices (There definitely is a way because Android knows when to switch orientation), please let me know in a comment so I can update my own code.
I use this:
#Override
public void onConfigurationChanged(Configuration _newConfig){
super.onConfigurationChanged(_newConfig);
int height = getWindowManager().getDefaultDisplay().getHeight();
int width = getWindowManager().getDefaultDisplay().getWidth();
if(width > height){
// landscape
}else{
// portrait
}
}
It is crude but effective.

Categories

Resources