Activity still recreated with configChanges - android

As I understand it, if you insert 'android:configChanges="orientation"' into the activity in the manifest, the activity will not be destroyed and recreated on an orientation change. To test this, I created a dead-simple app which does NOTHING. Then I inserted 'android:configChanges="orientation"' in the manifest. Then I added the following method:
#Override
public void onConfigurationChanged(Configuration newConfig) {
Log.v(TAG,"onConfigurationChanged:");
super.onConfigurationChanged(newConfig);
}
However, I'm still seeing onCreate() being called. The activity is still being recreated.
As if that weren't strange enough, I don't see onConfigurationChanged() being called when I put the emulator into landscape mode (Ctrl-F11). It's only called when I go back to portrait mode. Shouldn't it be called both ways? Isn't the configuration (orientation) being changed when I go into landscape as well as portrait modes? This makes no sense.
Anyway, this whole activity and orientation thing is driving me crazy.

Your screen size changes from 1200x800 to 800x1200 (for instance).
Since API 13, this will also raise a screenSize config change. The fix is:
android:configChanges="keyboardHidden|oritentation|screenSize"

However, I'm still seeing onCreate() being called. The activity is still being recreated.
The emulator emulates a device with a side-slider keyboard. The android:configChanges value that matches your - would be keyboardHidden, generally used in conjunction with orientation to handle non-keyboard devices (e.g., android:configChanges="keyboardHidden|orientation").
That being said, android:configChanges is not recommended in most cases. Use dynamic fragments and setRetainInstance(true), or use onSaveInstanceState() and onRetainNonConfigurationInstance() to allow the activity to be destroyed and recreated.

Related

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.
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.
You, probably could store your activity's current orientation in shared preferences in onStop() and restore it in onResume()

How can I prevent Android Activity from briefly entering portrait mode when I have specified landscape?

I have specified my Activity should be fixed to landscape, which works most of the time. Specifically, when the Activity is already running, and I launch a new instance of it from Eclipse, the Activity starts in Portrait and immediately changes to Landscape--but not before the View has already been told it was Portrait. So my View is initialized as Portrait, but gets a surfaceChanged immediately.
I have the following specified in my manifest:
<activity android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"
I have also tried:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
When I was targeting API level 7, I believe this worked fine. Now I target API level8, and a strange quirk has appeared.
In the oncreate method, the value of:
getResources().getConfiguration().orientation
is:
Configuration.ORIENTATION_PORTRAIT
Immediately after creating the Activity, the orientation is changed to Landscape, I receive a surfacechanged, and I can "fix" everything. But why is it ever portrait?
I suspect it has to do with the fact that the application is autorotated as it launches from a portrait screen. It seems bizarre that the application, which has been instructed to NEVER be in portrait, starts that way, and then quickly changes.
But, is there a way to not allow it to ever be in portrait?
I put this in my Activity's onCreate:
while (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
{
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
This resulted in it getting stuck there forever :)
Add this to your activity :
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
Define orientation in your menifest.
screenOrientation ="landscape"
OR
set the setRequestOrientation(...) before the setContentView(...) in your activity.

Activity restarts my game on screen rotation (Android)

I know this question was already asked, but mine is a little different:
I have 2 different layout files for my game; one for portrait mode and one for landscape. When I rotate the screen, the onCreate method restarts my game (creates all the elements again). I donĀ“t want this to happen, so I wrote this line in the manifest:
android:configChanges="orientation"
It works, onCreate is not called, but the new layout is not being showed properly!
I tried to put the following code in my Activity, but it just keeps doing weird things:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.gameview);
}
how can I fix this?
thanx guys
First of all understand how orientation changing in android works:
By default activity restarts on orientation changed event (and goes throw onCreate).
If you write android:configChanges="orientation" in manifest - it means it will not be recreated, but just remeasure and redraw view tree.
Comments about your code:
If you have different layout for different orientations - you have to recreate activity on orientation changed.
Method setContentView should called just once per activity lifecycle.
General way to handle this situation is:
Save game state in method onSaveInstanceState
In onCreate method restore game state if it is supplied (savedInstanceState param is not null).
Remove listening of configuration changing from manifest.
You should use onRetainNonConfigurationInstance() for save state and for restore state getLastNonConfigurationInstance() for any objects. Or hard-code set android:screenOrientation="portrait/landscape" in manifest.

How to know when the app is open (and not when onCreate is called)?

I want to track app opens in android but the problem is that onCreate for the main activity could be called multiple times when the orientation change. is there another way to track app open ?
Other methods than onCreate() could be used :
OnStart()
OnRestart()
OnResume()
You'll want to consult this page of the documentation in order to decide which one fits your needs better as they all get called in different situations.
Alternatively, you could always handle the orientation change yourself, that way the onCreate() method wouldn't be called when the screen rotates:
Modifications to the Manifest file:
<activity
android:name=".ActivityName"
android:configChanges="keyboardHidden|orientation" />
Add this method in the Activity :
/** {#inheritDoc} */
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
Hope this answers your question.
Do you want to consider handling orientation changes by yourself? That way, onCreate is not called when orientation changes (which is not a very good idea if you have different layouts for potrait and landscape). You can then rely on onStart method which is called when the screen is turned off/on, or when the activity resumes.
The activity is open when onCreate is called, and closes when onDestroy is called. Each onCreate will always be paired with an onDestroy; when the orientation changes, the activity is (by default) first destroyed, then recreated in the new orientation.

how to define the screen orientation before the activity is created?

I defined my activity to only be in portrait mode by :
android:screenOrientation="portrait"
When I take a picture with the camera function via intent, take this picture in landscape mode and turn the screen to portrait mode when saving it, i return to my activity again. What I dont understand is, that my activity for a short time is in landscape mode, is destroyed and then built again in portrait mode... as my onCreate ond onRestore functions need some time, the waiting time for the user is doubled...
Is there a workaround or something else?
You can also register your activity to explicitly handle any orientation changes by adding android:configChanges="orientation" to the activity definition and then overriding the onCofigurationChanged method in your activity like this:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
I'm not sure if it would help with your specific problem, but I remember doing this when I wanted an activity to only display in portrait mode. Let me know if it helps :)
Add android:configChanges="orientation" to your <activity> tag. This way the activity will not be recreated on orientation change, but will just receive a callback onConfigurationChanged which you can ignore.

Categories

Resources