1

This is a feature in API 18, and I can't get it to actually lock. I have been reading all night on how to manually handle your own configuration change, and tried many things, but the current code I have is not effective.

Goal: I need to have an activity, where, after the user takes a video (which brings them back to the app), the landing page should be either landscape or portrait, whichever way the user is holding the phone. But if they decide to go to landscape, I want to lock that position, so they cannot return to portrait (it causes video viewing errors if they go back). So they have a choice in the beginning, but then must stay in landscape if they choose that one. But how do I do this?

Here's what I have tried so far:

  1. Place this android:configChanges="keyboardHidden|orientation|screenSize" in the <activity> tag of my activity in the manifest.

  2. Override the onConfigurationChanged() method with this:

        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
    
            if (getResources().getConfiguration().orientation ==
                    Configuration.ORIENTATION_LANDSCAPE) {
                setContentView(R.layout.activity_make_photo_video_land);
            } else {
                setContentView(R.layout.activity_make_photo_video);
            }
    
            if (this.getResources().getConfiguration().orientation ==
                    ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE && Build.VERSION.SDK_INT
                    >= Build.VERSION_CODES.JELLY_BEAN_MR2){
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
            }
        }
    
  3. I have 2 layouts of xml, one for my portraits in layout folder, and one for landscapes in layout-land folder.

The result I am getting is that I can get the layouts to show on orientation change, but I cannot get it to lock. I am using a device with KitKat, so it should lock on there, but it doesn't.

Every post on here I've read about locking orientation (or workarounds for it) seems to be 3 or 4 years old and basically suggest what I am already trying. Any new information that anyone has out there?

Thanks.

Azurespot
  • 3,066
  • 3
  • 45
  • 73
  • 1
    I am interested in this issue. However code setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED) works for me. I tested with Android 4.2.x, Samsung Galaxy. And I used my Manifest like yours – The Original Android Apr 01 '15 at 03:06
  • If you care to read, I found SO link http://stackoverflow.com/questions/6599770/screen-orientation-lock – The Original Android Apr 01 '15 at 03:07
  • 2
    What's up with this "-1" vote again?! Could you report this to the SO webmaster? He/she could find out the culprit. I am sure it's annoying. Do you need me to upvote :) ? – The Original Android Apr 01 '15 at 03:08
  • I know! Thanks for the support. I did send an email to the Stack O support team. I haven't heard anything back though. Maybe I should try again. Thanks, an up-vote would be encouraging! :) I really do try my best to find resources before I ask questions. I think people are just as perplexed as I am and get frustrated? Not sure. – Azurespot Apr 01 '15 at 03:12
  • Btw, I realized that the `ActivityInfo.SCREEN_ORIENTATION_LOCKED` only works after my video comes back from the recording. But I was having other issues, so I'm trying a different route. The only way to save state (the Fragment retainer way is too confusing for me right now).. is to use the `android:configChanges="orientation|screenSize"` as you said, but having a hard time fetching the right layout when needed... but still working on it. – Azurespot Apr 01 '15 at 03:14
  • 1
    done! Good luck with the support team. – The Original Android Apr 01 '15 at 05:44
  • I have an idea about your UI design. How about have a button for the user to choose between portrait/landscape mode, and then save the mode for every image selected? I would like this feature in the Gallery app. This is, I think, only little difference in design. – The Original Android Apr 01 '15 at 05:50
  • 1
    Definitely not a bad idea... in my case though, it won't work, since they use the camera from the Android app, then come back to the app after it completes. So once they are in Camera, they can intuitively choose landscape or portrait, so it's a choice that is made in the Android camera itself. I'm trying to find a way to lock the screen AFTER they return though. That would help my app a lot. – Azurespot Apr 04 '15 at 02:33

4 Answers4

2

Did you try this?:

public static void lockOrientation(Activity activity) {
        Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        int rotation = display.getRotation();
        int currentOrientation = activity.getResources().getConfiguration().orientation;
        int orientation = 0;
        switch(currentOrientation)
        {
        case Configuration.ORIENTATION_LANDSCAPE:
            if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90)
                orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
            else
                orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
            break;
        case Configuration.ORIENTATION_PORTRAIT:
            if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270)
                orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
            else
                orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
        }
        activity.setRequestedOrientation(orientation);
    }

    public static void unlockOrientation(Activity activity) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
Green goblin
  • 9,898
  • 13
  • 71
  • 100
  • Thanks, I'd like to try that, however it doesn't accept the value of 0 for `orientation`. It wants only the constants (even though, once it runs, it would get that! ) But for now it thinks `orientation` is zero. :( – Azurespot Mar 31 '15 at 10:05
  • You can easily tweak the method to accept orientation – Green goblin Mar 31 '15 at 12:18
0

Use the android:scrreenOrientation="portrait" to fix(lock) your screen orientation and put it in your android mainfest file under the perticular activity. for portrait use "portrait" and for landscape use "lanscape". In my case it help me i think it will be help you try this.

 <activity
        android:name=".MainActivity"
        android:label="@string/title_activity"
        android:screenOrientation="portrait" />
Pranav P
  • 1,755
  • 19
  • 39
  • 3
    Thanks, but that is not what I was looking for. I need to get real-time locking of my view only **after** they choose landscape. So I don't want to permanently lock it from the start, but rather, only after the user chooses. – Azurespot Mar 31 '15 at 09:25
0

You can do it this way in your Java code:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

See http://developer.android.com/reference/android/app/Activity.html#setRequestedOrientation(int) for more info.

BUT - this is not really the best idea. All you are doing is hiding the error, which can occur in other ways (e.g. if the user locks the screen or receives a phone call while your video is playing). Orientation locking is hardly ever the answer. You should read this: http://developer.android.com/guide/topics/resources/runtime-changes.html

gkee
  • 771
  • 1
  • 7
  • 11
  • Thanks, I did try many different ways to set the orientation using that method, but it's producing buggy results. Like, turning the `VideoView` to black or not pulling the landscape view at all. When I go the route of taking `orientation` out of my Manifest, and rely on 2 different layouts (one in layout, the other in layout-land) that get chosen automatically, then the different views show, but `VideoView` turns black on config change. So I will look into that document you recommended. Maybe if I can save the state somehow, it will work(?) Thanks for the ideas. :) – Azurespot Mar 31 '15 at 10:16
  • 1
    Ah, finally found a good article on the topic. I think you are right, saving my activity's state via a retaining `Fragment` is the way to go. http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html – Azurespot Apr 01 '15 at 00:36
  • I think retaining a fragment is probably a good way to do it. An alternative is just to save the users position in the video in onSaveInstanceState, and then use seekTo http://developer.android.com/reference/android/media/MediaPlayer.html#seekTo(int) to get back there. That maybe simpler but not quite as good user experience, in that you'll have to load the video again (whereas if the fragment is retained all the content should also be retained?). – gkee Apr 01 '15 at 03:12
0

This could be a late answer. People still having trouble can read on.

You don't need to override onConfigurationChanged().

Just setting the flags for the Activity in the Manifest should do, as below:

<activity android:name=".MainActivity"
            android:screenOrientation="landscape"
            android:configChanges="orientation|keyboardHidden"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar">

...
...

</activity>

If you still have trouble, you can set multiple orientation flags such as this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    int o = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    o |= ActivityInfo.SCREEN_ORIENTATION_LOCKED;
    setRequestedOrientation(o);
    setContentView(R.layout.activity_main);
    ...
    ...
}

The above Java code locks the activity down to Landscape mode. There was never a need to set the orientation flag in Java. The Manifest route should work.

Ram Iyer
  • 1,621
  • 1
  • 23
  • 25