Search code examples
androidandroid-activityandroid-orientationorientation-changes

Resume an activity in the same orientation it had when it was paused?


I would like to ask if the following behaviour is possible and, if it is, how I can achieve it. I need this behaviour for a very specific reason.

I have two activities, I will call them Activity A and Activity B. Now let's look at this example:

From activity A, in portrait orientation, I launch activity B (which has a fixed landscape orientation). The user, as the activity B is displayed in landscape, obviously rotates the device. The activity B is finished and activity A is resumed. The user keeps the device in landscape orientation so the orientation of the activity A will immediately be changed just after is resumed.

What I want is avoid that the orientation of the activity A changes when the user goes back to it. I want to resume the activity A in the last orientation it had and only allow orientation changes after that.

Locking the orientation is not an option as I want to allow the user to change it anytime.

The android:configChanges="orientation|screenSize" solution is neither an option as I want my activity to be re-created after an orientation change.

Do I have an option to achieve what I want?

Thanks!

EDIT: I forgot to say that saving the current orientation before the activity A is destroyed and restoring it when it is created again is not an option too. Activity A should NOT be re-created after activity B finishes.

EDIT 2: I was thinking now and I realized that I could rewrite the question from another point of view.

I would like to avoid the re-creation of the activity A when it is resumed after activity B finishes.

Afaik, when the device orientation change occurs, a message is sent to ActivityThread (with value RELAUNCH_ACTIVITY). That causes the activity A to be re-created with the new screen orientation.

I want to avoid the activity A relaunch as that would solve my problems and would keep the last orientation it had.


Solution

  • I don't think it is possible to do this as you've described. When the user returns from the landscape activity to your previous activity you would need to lock the orientation to portrait (in order to ignore the landscape orientation that the phone is now in). Now, if the user rotates the phone, you won't see the rotation and you won't be able to change the orientation. Since you can't really tell whether the user just rotated the phone or if the rotation is due to returning from a landscape-only activity, you can't tell these 2 conditions apart.

    However, assuming that you can somehow differentiate between these 2 cases, try the following:

    If you don't want Android to recreate your activity on an orientation change (even only in certain circumstances), then you will need to tell Android that you want to handle orientation changes by yourself by setting

    android:configChanges="orientation|screenSize"
    

    in the manifest.

    Now you'll need to implement onConfigurationChanged() to get the behaviour that you want. In the case where your activity has launched another activity with fixed orientation, you'll want to save the current screen orientation before launching that activity. When the user returns to your activity Android won't destroy it and create a new instance it will just call onConfigurationChanged(). When you get the onConfigurationChanged() call you'll need to check if the user just rotated the device or if this is the result of returning from an orientation-locked activity. In the case where this is the return after launching another activity you can then lock the screen orientation to the previous orientation by calling setRequestedOrientation(). In the case where the user just rotated the phone, you can then either:

    • Recreate the activity by calling Activity.recreate() Note: this only works if you are running on API level 11 or higher
    • Recreate the activity by calling your own method that basically does everything necessary to recreate the Views (call setContentView()) and reset your member variables as if the activity were recreated
    • Recreate the activity by launching your activity again: startActivity(new Intent(this, this.class) and then calling finish() to get rid of the current instance.