Android, How to Not Destroy the Activity When I Rotate the Device

Android, how to not destroy the activity when I rotate the device?

For API 12 and below: add

android:configChanges="orientation"

Add "screenSize" if you are targeting API 13 or above because whenever your orientation changes so does your screen size, otherwise new devices will continue to destroy your activity. See Egg's answer below for more information on using "screenSize"

android:configChanges="orientation|screenSize"

to your Activity in AndroidManifest.xml. This way your Activity wont be restarted automatically. See the documentation for more infos

When I rotate the screen, the fragment is destroyed and returned to Activity, which opened that Fragment. But why he's doing so?

Why this is happening ?

Default Behavior, Actiivty is getting recreated on orientation change so your fragment are.

Explanation

You need to understand Activity Life Cycle to understand why this is happening.

enter image description here

First, “rotating the screen” is not the actual scenario we are talking about today. Because any configuration change will cause Android to restart your Activity. A configuration change might be the device rotating (because now we have a different screen layout to draw upon), or it could be a language switch (because we need to re-write all those strings, which may need more room now OR it could be the scary RTL switch!), or even keyboard availability.

By reloading your app, what the system is actually doing is calling onDestroy() and then immediately calling onCreate(). This way, your Activity is as fresh as possible, with all of the right creation data (even though the user has been with you the entire time).

Now you have following option -

  1. Either Fix Orientation for your app from AndroidManifest.xml

But oviously that is not a very good experience for user.


  1. Save activityState with onSaveInstanceState()

This method will be called before onDestroy(). And, when your Activity is created, there’s a matching step onRestoreInstanceState(), which will also be called automatically. All of these automatic steps mean that you can let the system worry about saving and loading your data, because you planned ahead and mapped out what was important. (Or, you can skip onRestoreInstanceState() and load your saved state from the Bundle that comes with onCreate().

In you integrate Fragment in activity, because activity is getting destroy() so your fragment will also destroy() and will be recreated.

enter image description here

Please take a good read on Handling Configuration Change and this.

Once you understood the concepts things will start falling into your but it will only happen if you will complete your learning curve.

Happy Coding !

Does screen rotation make an activity restart on newer Android versions?

The reason is because starting from Android 9, users need to press a new "rotation" button in the navigation bar when screen rotation happens. If you do not press it, the activity will not be destroyed and recreated. Please see this doc for more details.

Activity restart on rotation Android

Using the Application Class

Depending on what you're doing in your initialization you could consider creating a new class that extends Application and moving your initialization code into an overridden onCreate method within that class.

public class MyApplicationClass extends Application {
@Override
public void onCreate() {
super.onCreate();
// TODO Put your application initialization code here.
}
}

The onCreate in the application class is only called when the entire application is created, so the Activity restarts on orientation or keyboard visibility changes won't trigger it.

It's good practice to expose the instance of this class as a singleton and exposing the application variables you're initializing using getters and setters.

NOTE: You'll need to specify the name of your new Application class in the manifest for it to be registered and used:

<application
android:name="com.you.yourapp.MyApplicationClass"

Reacting to Configuration Changes [UPDATE: this is deprecated since API 13; see the recommended alternative]

As a further alternative, you can have your application listen for events that would cause a restart – like orientation and keyboard visibility changes – and handle them within your Activity.

Start by adding the android:configChanges node to your Activity's manifest node

 <activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">

or for Android 3.2 (API level 13) and newer:

<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name">

Then within the Activity override the onConfigurationChanged method and call setContentView to force the GUI layout to be re-done in the new orientation.

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myLayout);
}

Detect rotation (orientation change) before activity destroyed

After a lot of searching before posting my question, I finally came up with a solution based off of this post. I very simply check the current orientation and compare it to the previous state.

getResources().getConfiguration().orientation

If it is the different, the activity is restarting due to a rotation.

Sample Solution

I start by having two member variables to track the previous configuration and to mark rotation:

private int previousOrientation = Configuration.ORIENTATION_UNDEFINED;
private boolean rotating = false;

When the activity is started, in onCreate, I call checkAndSetOrientationInfo() which is defined as:

private void checkAndSetOrientationInfo() {
int currentOrientation = getResources().getConfiguration().orientation;
debugDescribeOrientations(currentOrientation);
if(previousOrientation != Configuration.ORIENTATION_UNDEFINED // starts undefined
&& previousOrientation != currentOrientation) rotating = true;

previousOrientation = currentOrientation;
}

The supporting functions are:

private String getOrientationAsString(final int orientation) {
if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
return "Landscape";
} else if(orientation == Configuration.ORIENTATION_PORTRAIT) {
return "Portrait";
} else return "Undefined";
}

private void debugDescribeOrientations(final int currentOrientation) {
Log.v("Orientation", "previousOrientation: " + getOrientationAsString(previousOrientation));
Log.v("Orientation", "currentOrientation: " + getOrientationAsString(currentOrientation));
}

And finally, for onPause:

@Override
protected void onPause() {
super.onPause();
if (isFinishing()) {
Log.v("onPause", "Finishing");
} else {
checkAndSetOrientationInfo();
if (rotating) {
Log.v("onPause", "Rotating");
} else {
Log.v("onPause", "Not rotating (task switch / home etc)");
// TODO put code here to pause mediaPlayer etc...
}
}
}

I asked and answered this question to help others with the same problem. I am also interested to see any comments about situations where this code might fail or other better solutions.



Related Topics



Leave a reply



Submit