8

I am developing an android app that should only run in portrait mode due to the layout not fitting on a phone's landscape screen. On tablets and netbooks, however, I want the app to only run in landscape mode.

I've now tried to check if the app is running on a tablet device and setting the corresponding requested orientation via setRequestedOrientation.

The problem is that the app crashes now when the device is not already held in the orientation I'm requesting, because I display a progressDialog shortly after the call to setRequestedOrientation, which seems to leak a window then.

Logcat says:

10-18 21:15:30.698: E/WindowManager(653): Activity has leaked window  com.android.internal.policy.impl.PhoneWindow$DecorView@41991418 that was originally added here
10-18 21:15:30.698: E/WindowManager(653): android.view.WindowLeaked: Activity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@41991418 that was originally added here
10-18 21:15:30.698: E/WindowManager(653):   at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:279)
10-18 21:15:30.698: E/WindowManager(653):   at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:215)
10-18 21:15:30.698: E/WindowManager(653):   at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:140)
10-18 21:15:30.698: E/WindowManager(653):   at android.view.Window$LocalWindowManager.addView(Window.java:537)
10-18 21:15:31.888: E/WindowManager(653): Activity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@41588040 that was originally added here
10-18 21:15:31.888: E/WindowManager(653): android.view.WindowLeaked: Activity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@41588040 that was originally added here
10-18 21:15:31.888: E/WindowManager(653):   at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:279)
10-18 21:15:31.888: E/WindowManager(653):   at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:215)
10-18 21:15:31.888: E/WindowManager(653):   at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:140)
10-18 21:15:31.888: E/WindowManager(653):   at android.view.Window$LocalWindowManager.addView(Window.java:537)
10-18 21:15:34.168: E/AndroidRuntime(653):  at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:599)
10-18 21:15:34.168: E/AndroidRuntime(653):  at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:336)
10-18 21:15:34.168: E/AndroidRuntime(653):  at android.view.WindowManagerImpl$CompatModeWrapper.removeView(WindowManagerImpl.java:151)

What could I do to prevent this crash? Any help would be highly appreciated.

EDIT: As I was not able to solve this, I finally managed to edit my Layout so that it now allows usage in portrait and landscape mode.

FD_
  • 12,947
  • 4
  • 35
  • 62

2 Answers2

13

Do you have any source code that you could show? That could help identify the problem.

I actually had the exact same problem. But it was only happening for some of my activities.

When the screen orientation changes, Android actually destroys and recreates the activity.

So, I had code that looked like this.

   @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        setContentView(R.layout.displayscreen);

        bottomButton = (Button) findViewById(R.id.bottomButton);
        bottomButton.setOnClickListener(bottomButtonClick);
        bottomButton.setTypeface(font);
        bottomButton.setTextSize(16);
}

See what was happening is that the view was not attached correctly to the window manager. So I decided that the oncreate was perhaps not the best spot to be doing this.

Instead I added it to my on Resume and it works. Like so:

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

        bottomButton = (Button) findViewById(R.id.bottomButton);
        bottomButton.setOnClickListener(bottomButtonClick);
        bottomButton.setTypeface(font);
        bottomButton.setTextSize(16);
}

@Override
protected void onResume() {
    super.onResume();
    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

Unfortunately this also causes the the activity to still get destroyed and recreated. Calling the onCreate and onResume twice... Not good right?

So to fix this issue. You have to add this into your android manifest for your activity.

android:configChanges="keyboardHidden|orientation"

An Example:

<activity 
    android:name="com.Test.Info.DisplayInfo"
    android:configChanges="keyboardHidden|orientation"
    android:label="@string/info">
</activity>

This code prevents the destroy/recreate cycle.

Hopefully this helps!

Cheers

Dave
  • 3,178
  • 5
  • 28
  • 44
  • 1
    Thanks for writing such a long answer, but unfortunately it did not solve my problem. – FD_ Oct 19 '12 at 12:43
  • No problem. Sorry it didn't help you. Next time if you add some source code, it will help in tracking down your specific issue. I had a similar problem, and this worked for my specific issue. Glad you got it working though. – Dave Oct 19 '12 at 21:06
  • 1
    Thanks, your answer saved me Dave! Actually, you just have to set the `android:configChanges="orientation"` in the manifest and call `setRequestedOrientation()` at the beginning of `onCreate()` ;) – Christophe Longeanie Jul 11 '13 at 10:15
  • Your answer is correct but at the same time why not define setScreenOrientation in onCreate while adding the configChanges for activity in manifest.xml .i tried like this it was working great... – Santosh Oct 25 '13 at 05:17
  • The onResume code is not required. If you manually set the orientation in onResume, you will not get the onConfigurationChanged event fired. – Varun Chatterji May 13 '14 at 14:48
  • 1
    @FD_ Maybe use `android:configChanges="orientation|screenSize"` – William Ardila Aug 11 '16 at 17:59
9

If you use

setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR);

to temporarily lock, and

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

to unlock the screen rotation, maybe you ran into the following problem.

If you use this method to lock the screen orientation and the device is not in its default orientation, it will switch to the default orientation, destroying and creating your activity. Your app will crash, due to the fact that your trying to update some destoryed progressDialog.

Community
  • 1
  • 1
darksaga
  • 2,166
  • 2
  • 18
  • 21