I'm interested to know which methods are overridden, when an Android device is rotated (i.e. when configuration changes)?
onSaveInstanceState(...), onConfigurationChanged(...), onRestoreInstanceState(...) - something similar to this?
It will be also interesting for me to listen about the whole process connected with changing a configuration. Thanks.
According to the android developer reference you have to use:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
For more information see: http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
You could be interested in seeing: http://developer.android.com/guide/topics/manifest/activity-element.html#config
Here you can find all configuration listener you can listen.
Remember to put them in the android manifest:
<activity
android:configChanges=["orientation"]
. . .
</activity>
Hope this helps...
When you rotate the device your Activity will re-create and all the variables will be re-initialized. So, in that case if you want to some values to remain same on Rotation also you can store their state using the onSaveInstanceState() and you can restore in onCreate() again by checking Bundle is not null.
if(savedInstanceState != null){
// get the restore value from the Bundle
}
Where as onConfigurationChanged() will be called when you rotate the Device(Note that this will only be called if you have selected configurations you would like to handle with the configChanges attribute in your manifest). From the parameter you will get the new device configuration.
If you don't want your Activity to get re-created on rotation of Device then you have to add this line to your activity tag in the AndroidManifest file.
android:ConfigChanges="keyboardHidden|orientation"
From android developers...
To retain an Object during a runtime configuration change:
Override the onRetainNonConfigurationInstance() method to return the Object you would like to retain.
When your Activity is created again, call getLastNonConfigurationInstance() to recover your Object.
Android calls onRetainNonConfigurationInstance() between onStop() and onDestroy() when it shuts down your Activity due to a configuration change. In your implementation of onRetainNonConfigurationInstance(), you can return any Object that you need in order to efficiently restore your state after the configuration change.
A scenario in which this can be valuable is if your application loads a lot of data from the web. If the user changes the orientation of the device and the Activity restarts, your application must re-fetch the data, which could be slow. What you can do instead is implement onRetainNonConfigurationInstance() to return an object carrying your data and then retrieve the data when your Activity starts again with getLastNonConfigurationInstance().
Look at here for more info Retaining an Object During a Configuration Change you can also find example over their..
Thanks..
Go to Manifest and add:
android:configChanges="orientation|screenSize"
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"
android:configChanges="orientation|screenSize"
/>
In Main Activity: Copy and Paste this code:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
All Done -
Related
After the orientation changes, this method is called:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
But how do I take action BEFORE the guidance change? I need it before it changes, I save some things in SQLite.
Is there any way to do this?
Your activity calls that onCreate() with different execution params in every orientation changes. But you can handle those changes by configuring configChanges tag in the manifest file.
For example, the following manifest code declares an activity that handles both the screen orientation change and keyboard availability change:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name">
you can find all the details about this configChanges by navigating this https://developer.android.com/guide/topics/resources/runtime-changes android official documentation.
You can use this knowledge and do what you want when triggering this method while orientation changes.
I understand that when a device rotates, Android destroys and recreates the current activity in order to load orientation-specific resources. To save state, I can use onSaveInstanceState(Bundle outState)and the regular onCreate(Bundle savedInstanceState) but this saves and restores state each time the app is destroyed/created for any reason.
What I want to do is to save/restor state only when the app was destroyed/created because of an orientation change; when the app is destroyed because of memory or the user kills it, I'm not interested in saving state. ¿How can I do this?
You could set the onConfigurationChange() method. To do that you need to override it in your Activity's code and set a few parameters in your Manifest:
MainActivity.java
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
You have to add these attributes (android:configChanges="orientation|screenSize") to your activity, set as many as you want to handle:
AndroidManifest.xml
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize"
android:label="#string/app_name">
Be careful, with this setup, your activity will not restart, as mentioned in the docs, so, if you want to restart it you will need to implement a manual restart.
Now, when one of these configurations change, MyActivity does not
restart. Instead, the MyActivity receives a call to
onConfigurationChanged().
Link to the main documentation.
Turns out my question was wrong from the beginning.
When the device rotates, Android calls onSaveInstanceState(Bundle outState) and onRestoreInstanceState(Bundle savedInstanceState) as a way for the developer to save/restore state. When the activity is destroyed via back button or finish(), onSaveInstanceState is not called and the savedInstanceState bundle that's passed to onCreate() is null. So trying to answer the "was this created after a rotation or not?" question is irrelevant.
Posted in case someone has the same question and thanks to all that took time to read and help.
Here is the structure of my application.
MainActivity.java calls FragmentActivity.java,
FragmentActivity.java calls GameView.java
GameView.java calls Thread.java.
Basically all the gaming logic will be handled by GameView and its thread.
I don't know how to prevent from restarting the game when there is a orientation change.
If i paused the thread and resume it, the app crashes and also i can not use onSaveInstanceState method in Gameview.java
Any help?
It is completely possible through the Android manifest.
Just add in the activity declaration, in which you want to disable the restarting the following attribute:
android:configChanges="orientation|screenSize"
Then you can overwrite the onConfigurationChanged() in your activity and you get the callback which event just happened. In your case the orientation change. And with this approach the activity doesn't restart, when your orientation changes.
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
You are looking for onResume() and on pause() ... You store values into a bundle in pause and instantiate those values on the resume method and show a dialog as this happens to prevent the user from noticing the obvious.
You can have some control over what happens on orientation change, by defining an Application class in your manifest file, and overriding public method onConfigurationChanged().
Base class for those who need to maintain global application state.
You can provide your own implementation by specifying its name in your
AndroidManifest.xml's tag, which will cause that class
to be instantiated for you when the process for your
application/package is created.
You just need to check for newConfig == Configuration.ORIENTATION_LANDSCAPE and such. At this point you might want to reload resources to get things working.
I have a simple activity that loads a bitmap in onCreate. I find that if I rotate the device I can see from the logs that onCreate called again. In fact, because all instance variables are set to default values again I know that the entire Activity has been re-instantiated.
After rotating 2 times I get an FC because not enough memory can be allocated for the bitmap. (Are all instances of the activty still alive somewhere? Or does the GC not clean up fast enough?)
#Override
public void onCreate(Bundle savedInstanceState) {
File externalStorageDir = Environment.getExternalStorageDirectory();
File picturesDir = new File(externalStorageDir, "DCIM/Camera");
File[] files = picturesDir.listFiles(new FilenameFilter(){
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".jpg");
}});
if (files.length > 0) {
Bitmap bm = BitmapFactory.decodeStream(new FileInputStream(files[0]));
ImageView view = (ImageView) findViewById(R.id.photo);
view.setImageBitmap(bm);
}
}
From all that I read, onCreate should be called once during the lifetime of an application. Am I wrong about this? How can re-orienting the device cause the activity to be recreated?
android:configChanges="keyboardHidden|orientation|screenSize"
Caution: Beginning with Android 3.2 (API level 13), the "screen size"
also changes when the device switches between portrait and landscape
orientation. Thus, if you want to prevent runtime restarts due to
orientation change when developing for API level 13 or higher (as
declared by the minSdkVersion and targetSdkVersion attributes), you
must include the "screenSize" value in addition to the "orientation"
value. That is, you must decalare
android:configChanges="orientation|screenSize". However, if your
application targets API level 12 or lower, then your activity always
handles this configuration change itself (this configuration change
does not restart your activity, even when running on an Android 3.2 or
higher device).
From docs: http://developer.android.com/guide/topics/resources/runtime-changes.html
What happen when orientation changed
Life Cycle of orientation
onPause();
onSaveInstanceState();
onStop();
onDestroy();
onCreate();
onStart();
onResume();
---- app recreated and now is running ---
If you do long operation in onCreate() and want prevent re-create your activity add configChanges attribute in your mainfest
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/app_name">
screenSize if you targeting api >= 13
Activity is recreated after each rotation by default. You can override this behaviour with configChanges attribute of the activity tag in AndroidManifest. For further details and different options, see http://developer.android.com/guide/topics/resources/runtime-changes.html
Actvity Lifecycle when you rotate screen
onPause
onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onResume
If you want to prevent FC from not enough memory, you need to deallocate resources in onStop() or onPause(). this allows you to use fresh memory in onCreate().
This is an alternate solution to preventing the recreation of the activity by using
android:configChanges="keyboardHidden|orientation"
As sometimes your activity's layout is different in portrait and landscape (layout, layout-land).
preventing recreate on orientation change will prevent your activity from using the other orientation's layout.
Yes, activity's onCreate() is called everytime when the orientation changes but you can avoid the re-creation of Activity by adding configChanges attribute of Activity in your AndroidManifest file in the activity tag.
android:configChanges="keyboardHidden|orientation"
On Create method will call everytime when you do orientation, to avoid this you have to use
//Define Below in you Manifest file.
<activity
android:name="com.ecordia.activities.evidence.MediaAttachmentView"
android:configChanges="keyboardHidden|orientation|screenSize"
</activity>
//Define Below in your activity.
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
//your code
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
//your code
}
}
It will works like a charm!!
Manifest XML activity Tag:
android:configChanges="keyboardHidden|orientation"
#Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
}
Use the above code to perform changes related to orientation in your Activity Java Code
Cheers!!!
One of the most common and suggested “solutions” to dealing with orientation changes is to not deal with them. You can do this by setting the android:configChanges flag on your Activity in AndroidManifest.xml as shown below:
<activity
android:name=".MyActivity"
android:label="#string/title_my_activity"
android:configChanges="orientation|screenSize|keyboardHidden" />
This is NOT the correct way to deal with orientation changes.
CORRECT way is to implement the onSaveInstanceState method (this could be in your Activity, Fragment or both) and place the values you need to save in the Bundle argument that gets passed to the method.
It is nicely described here: http://code.hootsuite.com/orientation-changes-on-android/
While it may seem a bit tedious to implement, handling orientation changes properly provides you with several benefits: you will be able to easily use alternate layouts in portrait and landscape orientations, and you will be able to handle many exceptional states such as low memory situations and interruptions from incoming phone calls without any extra code.
While the Manifest way may work, there is a better and proper solution for these types of problems. The ViewModel class. You should have a look here: https://developer.android.com/topic/libraries/architecture/viewmodel
Basically, you extend the ViewModel class and define all the data members in it which we want to be unchanged over re creation of the activity (in this case orientation change). And provide relevant methods to access those from the Activity class. So when the Activity is re created, the ViewModel object is still there, and so are our data!
Kindly see my way of doing it:-
http://animeshrivastava.blogspot.in/2017/08/activity-lifecycle-oncreate-beating_3.html
snippet is:-
#Override
protected void onSaveInstanceState(Bundle b) {
super.onSaveInstanceState(b);
String str="Screen Change="+String.valueOf(screenChange)+"....";
Toast.makeText(ctx,str+"You are changing orientation...",Toast.LENGTH_SHORT).show();
screenChange=true;
}
#Override
public void onCreate(Bundle b) {
super.onCreate(b);
ctx=getApplicationContext();
if(!screenChange) {
String str="Screen Change="+String.valueOf(screenChange);
// ...
}
}
I had the same problem, in which my onCreate is called multiple times when the screen orientation is changed. My problem got solved when i add android:configChanges="orientation|keyboardHidden|screenSize" in the activity tag in manifest
I had the same problem and I did some workaround
Define didLoad boolean variable with false value
private boolean didLoad = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
if (!this.didLoad){
// Your code...
this.didLoad = true;
}
I simply need nothing to change when the screen is rotated. My app displays a random image when it first loads and rotating the device should not select another random image.
How can I (simply) make this behavior stop?
There are generally three ways to do this:
As some of the answers suggested, you could distinguish the cases of your activity being created for the first time and being restored from savedInstanceState. This is done by overriding onSaveInstanceState and checking the parameter of onCreate.
You could lock the activity in one orientation by adding android:screenOrientation="portrait" (or "landscape") to <activity> in your manifest.
You could tell the system that you meant to handle screen changes for yourself by specifying android:configChanges="orientation|screenSize" in the <activity> tag. This way the activity will not be recreated, but will receive a callback instead (which you can ignore as it's not useful for you).
Personally I'd go with (3). Of course if locking the app to one of the orientations is fine with you, you can also go with (2).
Xion's answer was close, but #3 (android:configChanes="orientation") won't work unless the application has an API level of 12 or lower.
In API level 13 or above, the screen size changes when the orientation changes, so this still causes the activity to be destroyed and started when orientation changes.
Simply add the "screenSize" attribute like I did below:
<activity
android:name=".YourActivityName"
android:configChanges="orientation|screenSize">
</activity>
Now, when you change orientation (and screen size changes), the activity keeps its state and onConfigurationChanged() is called. This will keep whatever is on the screen (ie: webpage in a Webview) when the orientation changes.
Learned this from this site:
http://developer.android.com/guide/topics/manifest/activity-element.html
Also, this is apparently a bad practice so read the link below about Handling Runtime Changes:
http://developer.android.com/guide/topics/resources/runtime-changes.html
You just have to go to the AndroidManifest.xml and inside or in your activities labels, you have to type this line of code as someone up there said:
android:configChanges="orientation|screenSize"
So, you'll have something like this:
<activity android:name="ActivityMenu"
android:configChanges="orientation|screenSize">
</activity>
Hope it works!
<activity android:name="com.example.abc"
android:configChanges="orientation|screenSize"></activity>
Just add android:configChanges="orientation|screenSize" in activity tab of manifest file.
So, Activity won't restart when orientation change.
It's my experience that it's actually better to just deal with the orientation changes properly instead of trying to shoehorn a non-default behavior.
You should save the image that's currently being displayed in onSaveInstanceState() and restore it properly when your application runs through onCreate() again.
This solution is by far the best working one. In your manifest file add
<activity
android:configChanges="keyboardHidden|orientation|screenSize"
android:name="your activity name"
android:label="#string/app_name"
android:screenOrientation="landscape">
</activity
And in your activity class add the following code
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
//your code
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
//your code
}
}
In manifiest file add to each activity this. This will help
android:configChanges = "orientation|keyboard|keyboardHidden|screenLayout|screenSize"
add android:configChanges="keyboardHidden|orientation|screenSize" for all the app activities tags in manifest.
Just add this to your AndroidManifest.xml
<activity android:screenOrientation="landscape">
I mean, there is an activity tag, add this as another parameter. In case if you need portrait orientation, change landscape to portrait. Hope this helps.
just use : android:configChanges="keyboardHidden|orientation"
As Pacerier mentioned,
android:configChanges="orientation|screenSize"
All above answers are not working for me. So, i have fixed by mentioning the label with screenOrientation like below. Now everything fine
<activity android:name=".activity.VideoWebViewActivity"
android:label="#string/app_name"
android:configChanges="orientation|screenSize"/>
http://animeshrivastava.blogspot.in/2017/08/activity-lifecycle-oncreate-beating_3.html
#Override
protected void onSaveInstanceState(Bundle b)
{
super.onSaveInstanceState(b);
String str="Screen Change="+String.valueOf(screenChange)+"....";
Toast.makeText(ctx,str+"You are changing orientation...",Toast.LENGTH_SHORT).show();
screenChange=true;
}
Prevent Activity to recreated
Most common solution to dealing with orientation changes by setting the android:configChanges flag on your Activity in AndroidManifest.xml. Using this attribute your Activities won’t be recreated and all your views and data will still be there after orientation change.
<activity
android:name="com.example.test.activity.MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"/>
this is work for me😊😊😊
Save the image details in your onPause() or onStop() and use it in the onCreate(Bundle savedInstanceState) to restore the image.
EDIT:
More info on the actual process is detailed here http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle as it is different in Honeycomb than previous Android versions.
I dont know if the a best solution, but i describe it here:
First of all, you need certificate with you class Application of your app is in your manifest of this:
<application
android:name=".App"
...
Second, in my class App i did like this:
public class App extends Application {
public static boolean isOrientationChanged = false;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onConfigurationChanged(#NotNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ||
newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
isOrientationChanged = true;
}
}
}
Third, you need to set a flag to Orientation Change, in my case, I always set it when the previous activity within the app navigation is called, so only calling once when the later activity is created.
isOrientationChanged = false;
So every time I change the orientation of my screen in that context, I set it every time it changes this setting, it checks if there is a change in orientation, if so, it validates it based on the value of that flag.
Basically, I had to use it whenever I made an asynchronous retrofit request, which he called every moment that changed orientation, constantly crashing the application:
if (!isOrientationChanged) {
presenter.retrieveAddress(this, idClient, TYPE_ADDRESS);
}
I don't know if it's the most elegant and beautiful solution, but at least here it's functional :)
Add this code after the onCreate ,method in your activity containing the WebView
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
}