Showing a rotation-locked activity programatically in Android

Sometimes you need an activity showing in a locked orientation (i.e. no rotation allowed), but you need to decide which orientation should be the activity display dynamically by code. In my case, I had to implement a chroma-keyed camera app and the backgrounds where either landscape or portrait. When the user tapped the background to use I had to decide the orientation and lock the new camera activity to this orientation.

My first thought was using setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_x); on the onCreate() in the activity, but I found that was not reliable. In some cases the screen didn’t lock and rotated freely. I was doing my tests in a Honeycomb Galaxy Tab, so I’m not sure if in 4.x this method should work.

Finally, the method I used and that worked flawlessly was declaring two different activities in the manifest, using android:screenOrientation attribute:

<activity
 android:name="com.xrubio.retrats.activity.ActivityCameraLandscape"
 android:screenOrientation="landscape"
 android:theme="@style/AppTheme.NoActionBar" />
<activity
 android:name="com.xrubio.retrats.activity.ActivityCameraPortrait"
 android:screenOrientation="portrait"
 android:theme="@style/AppTheme.NoActionBar" />

The trick is not duplicate the whole class code, but to put all the logic in a base class ActivityCameraBase and derive two subclasses with the names ActivityCameraLandscape and ActivityCameraLandscape. Also, there will be a single layout file, for both orientations.

Activities detail

package com.xrubio.retrats.activity;

// imports here

// This class is used to be able to have two different orientations,
// locked at manifest level, so we're able to select which orientation
// we want the camera be locked at programatically, without having to
// reimplement everything again.
public class ActivityCameraBase extends Activity {

  @Override
  public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);

    // remaining initialization stuff...
  }

  // remaining activity logic...
}
package com.xrubio.retrats.activity;

public class ActivityCameraLandscape extends ActivityCameraBase {
  // Look, ma, the class is empty!
}
package com.xrubio.retrats.activity;

public class ActivityCameraPortrait extends ActivityCameraBase {
  // Look, ma, the class is empty!
}

Notice, however, that you can have two different layouts if you need your layout to be different in landscape and portrait, but keep the logic the same. In this case you will put your portrait layout in the regular layout directory, and your landscape layout in the layout-land directory, using the same name.

Different layouts detail