سؤال

I believe to have stumbled upon an inherent glitch in the orientation handling of Android.

I have an activity A

setContentView(R.layout.activity_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

No sensor implies that the Activity A won't be affected by the physical device rotation.

I also have an activity B which has an overridden onSaveInstanceBundle

/*Will be called before orientation change*/
@Override
protected void onSaveInstanceState(Bundle currentState) {
      super.onSaveInstanceState(currentState);
      currentState.putBoolean(ApplicationConstants.Messages.ORIENTATION_CHANGED , true);
      currentState.putBoolean("RESTART", true);

      currentState.putString(ApplicationConstants.Messages.CURRENT_LANGUAGE,currentLocale);

    }

onSaveInstance is always called when the orientation of the screen is changed. Like A, B also has the following under onCreate()

setContentView(R.layout.activity_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

Now here comes the conundrum.

I press a button from A, which is programmed to invoke B while I am holding the device in normal portrait mode. I have a breakpoint attached to onSaveInstance

As expected, onSaveInstance is not called when B is invoked

However, here is a strange fact. If I hold the device in landscape mode, and then invoke B, B's onSaveInstance is invoked, and as the program is suspended upon the breakpoint, we can see that the device screen has landscaped.

Hence even though I have NO SENSOR argument on the activity, the sensor is in fact still working. And between an activity switch IF DONE WHILE WE HOLD THE DEVICE IN LANDSCAPE, the target activity starts in landscape. After I let the breakpoint go, B resumes to portrait view.

I have a long story as to why this is affecting a project that I am developing. I wished to know if anyone has any insights into this situation.

To sum up, my question is:

Is it true that during an activity switch, the Android system ignores the specified orientation, and by default uses the device's physical position? I can't set the orientation in the androidManifest. I have noted this is not the case if we put the orientation mode in the manifest.

هل كانت مفيدة؟

المحلول 2

EDIT: Leaving the below for reference, but this clearly does NOT actually work. :(


He wants the application to be locked to portrait on cellphones, and be free to rotate on tablets.

Ugh. Well, you actually can accomplish this through the manifest. How you do it depends on what you want to define as a "tablet". Let's assume the cutoff is the Google-suggested sw600dp (smallest width of 600dp is a good breakpoint for a 7" tablet).

You can make the following file structure in your res folder:

res
    - values
        - styles.xml
    - values-sw600dp
        - styles.xml

In your values/styles.xml (this will be your non-tablet style), define the following styles for your Activity:

<!-- This will be a base style that will affect both tablet and non-tablet -->
<style name="BaseTheme" parent="{{pick a base theme here -- e.g. Theme.Light}}"/>

<!-- This is the local style that will be used on devices whose smallest width
     is less than 600dp -->
<style name="BaseTheme.Activity">
    <item name="android:screenOrientation">portrait</item>
</style>

In your values-sw600dp/styles.xml:

<!-- This is the local style that will be used on devices whose smallest
     width is greater than or equal to 600dp. We define nothing here other
     than the fact that the style exists, so it will have the default screen
     orientation - that is, it will rotate freely. -->
<style name="BaseTheme.Activity"/>

Now, in your AndroidManifest.xml, inside your activity tag, add:

android:theme="@style/BaseTheme.Activity"

And you should have the desired result. However, you should first remove all of the Java code you added to try to manage this yourself, as it will likely conflict with this causing unexpected results.

نصائح أخرى

Is it true that during an activity switch , the android system ignores the specified orientation , and by default uses the device's physical position ? .

That's not exactly true, because you are not specifying an orientation. SCREEN_ORIENTATION_NOSENSOR just means "ignore the sensor from now on and keep it in the current orientation". That doesn't get called until onCreate() runs. Nowhere are you saying "lock into portrait from the very start".

I can't set the orientation in the androidmanifest . I have noted this is not the case if we put the orientation mode in the manifest.

Out of curiousity, why can't you? That's the most common way to do it:

android:screenOrientation="portrait"
android:configChanges="orientation|screenSize"

The reason it locks in correctly with the manifest entries is that the ActivityManager knows it should be locked in before the Activity is ever run.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top