Android - Activity Reload on Rotation - android

I know this is a duplicate question, and I know that when the device is rotated, the OnCreate method is called again, and I want to keep it like this; I don't want to go through the steps of overriding onConfigurationChanged or sub-classing my Application class because android is doing the reloading in the best way (especially on saving current values and status).
However, I have some commands inside the OnCreate method which I don't want to execute them if the Activity is reloaded due to Rotation, so is there any property/method that can tell if OnCreate is triggered due to first Application start or due to Orientation change?
For example:
if(< OnCreate triggered due to Orientation > == false)
// Execute my commands...
else
// Do nothing...
Alternatively, do we have any events in Android to be triggered before OnCreate or before OnConfigurationChanged?

Why not store the current orientation in SharedPreferences and compare the current orientation to the stored value in onCreate (and then save the new orientation to SharedPreferences)?
That should provide the functionality that you require, unless I've misunderstood something.

Try using onSaveInstanceState, if you want to save some state information before your activity gets destroyed and then onRestoreInstanceState to retrieve it.
You can also use getRequestedOrientation() in onCreate to get the new Orientation.
You can also use this in onCreate()
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
int orientation = display.getOrientation();

The Activity class has a special
method called
onRetainNonConfigurationInstance().
This method can be used to pass an
arbitrary object your future self and
Android is smart enough to call this
method only when needed.
Read more here.

Related

How to know if calling setRequestedOrientation() will restart an activity?

So my app allows users to set a specific orientation in the preferences.
Then I call in the activity the next method
setRequestedOrientation(#ActivityInfo.ScreenOrientation int requestedOrientation)
But I also want to know if it's going to trigger activity recreation so I would not init other
stuff
Is it possible to know if will recreate an activity?

Android Activity instance state

What is the significance of:
super.onCreate(null);
instead of
super.onCreate(savedInstanceState);
With this change, I am able to avoid many problems that otherwise plague my Activitys each time a configuration change occurs (rotation, locale shift, permission toggle). It seems that with this change, the Activity is started afresh whenever a configuration change triggers it to restart. And I don't seem to lose any data or process state by doing this: all my Activitys are restored exactly to their former state.
My question is, can I do this with impunity henceforth, or am losing something in the bargain? I don't really understand why this works, whether it is safe or not, and what unintended effects it may have on my app.
I chanced upon this trick here.
Related Questions:
Calling super.onCreate() with null parameter?
Will 'Bundle savedInstanceState' be alive after Application is being killed?
Activity state instance - insights?
Activity's instance state: what is automatically stored and restored
onCreate() call first when activity is about to create, Also Android System manage activity lifecycle and can kill the activity with saving its instanceState, in case if acitvity out of focus for user for long time and system is on low memory situation.
An activity has essentially four states
super.onCreate(null) : Would always create activity as it is creating fisrt time , even Android system provide its savedInstanceState, and does't matter what orientation configurations are.
super.onCreate(savedInstanceState) : Activity can use 'savedInstanceState' to reset its state or component where it was last.
To achive this, acitivty's instance state need to be persist before activity lost user attention( that could be onStop or onDestroy)
savedInstaceState can also be important to handle if activity configuration got changed, Please check acitvity life cycle behavior on Configuration change
am losing something in the bargain?
Only if you are working with Fragments. see Calling super.onCreate() with null parameter?
Yes, onCreate(...) is necessary to start an Activity, but passing Bundle as an argument is required when you are working with fragments.
What did you infer from that?
The argument savedInstanceState is anyway null by default. So you aren't really losing anything in a bargain.
But wait, we usually use Bundles to maintain orientation change, right?
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">
Now, when one of these configurations change, MyActivity does not restart. Instead, the MyActivity receives a call to onConfigurationChanged(). This method is passed a Configuration object that specifies the new device configuration. By reading fields in the Configuration, you can determine the new configuration and make appropriate changes by updating the resources used in your interface. At the time this method is called, your activity's Resources object is updated to return resources based on the new configuration, so you can easily reset elements of your UI without the system restarting your activity.
the following onConfigurationChanged() implementation checks the current device orientation:
#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();
}
}
But Remember: When you declare your activity to handle a configuration change, you are responsible for resetting any elements for which you provide alternatives. If you declare your activity to handle the orientation change and have images that should change between landscape and portrait, you must re-assign each resource to each element during onConfigurationChanged().
As far as I know a lot of data is saved in the bundle savedInstanceState.
E.g. all the views' states in your current layout, such as the current content of any EditText or CheckBox.
You could also look up some official sources to check whether you need to keep some data.
Here's a nice article about it
Basically it says that all View class implements the methods onRestoreInstanceState and onSaveInstanceState, which are saving and restoring any temporary states they were in before the state change.
The savedInstanceState is a reference to a Bundle object that is passed into the onCreate method of every Android Activity. Activities have the ability, under special circumstances, to restore themselves to a previous state using the data stored in this bundle.
It is very important to use savedInstantState to get values from Intent which is saved in the bundle.
All your data stored in class variables or local variables is lost whenever you change rotation of device, but in your activity it looks like you have not stored any data as long as user enters any data, but instead you are perhaps reading data on click of a button or something like that, your activity will behave and work normally, and all user inputs like text inside EditText will be restored by Android itself, because it identifies "IDs" (android:id="#+id/anyID") allotted to each view and can restore by itself all the values inserted by user.
I hope this this helps you...
Happy coding :)

Is there a way to know that an Activity was recreated because of a device rotation

I have an activity class that locks itself with a custom PIN whenever it is resumed/recreated (so that I can lend my phone to someone secure in the knowledge they can't see that app's data).
The problem this causes is that rotating the device recreates the Activity and redisplays the PIN lock, which is a bit unsmooth.
So, is there some way the Activity to know either
I am being destroyed because of an orientation change.
I am being created as a result of an orientation change.
I would like to avoid solutions based on android:configChanges="orientation|screenSize" if possible.
EDIT: For posterity, I ended up doing this by having all Activities in the app inherit from this LockableActivity class.
A very simple solution is to check the time passed between 'onPause' and 'onResume'. If it is less than 0.2 seconds then you haven't handed your phone over ...
In fact, you could make this a user controllable security feature: how long away from the activity before pin entry is needed again could be set by the user.
For the truly obsessive, you could ask the user to reorient their phone during the set up phase to determine the associated time lapse and set that as the minimum.
As noted elsewhere, you could also use onSaveInstanceState. In this approach that is when you would store the time for comparison later.
Put the below code in your activity, it will get triggered when the device is rotated
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//perform your operations here
}
If you also want to check whether it is in landscape or portrait mode , you can apply below conditions
if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
}
else {
}
If your activity is normally destroyed, onSaveInstanceState() will never be called. During orientation change (or any other change that needs to load different resources), onSaveInstanceState() will be called. In this method, you can save your data that you want your activity to have during it's re-creation.
If your activity is normally created, savedInstanceState will be null. But if it was created because of re-creation (like change in orientation), then savedInstanceState will not be null and you can use this to fetch the data that you saved during onSaveInstanceState().
It's a bad idea to override onConfigurationChanged(), instead you could just use these methods that Android provide to persist your data or application logic . In your case, it could be something like this in your onCreate().
if(savedInstanceState != null){
boolean loggedIn= savedInstanceState.getBoolean("LoggedIn",false);
if(!loggedIn){
// Not logged in, hence show pinlock
}
}
You could do something like this.

Save cache when rotate device

I have a Gallerywiew.
I'm using lazyload to download images but when I rotate device it reloads all images and does not use the cache.
If I do android:configChanges="keyboardHidden|orientation" the current images are in size of latest orientation.
To get the images to show full size I do:
Display display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Overriding onConfigurationChanged() is discouraged because there's so much work you have to do to get it right.
What you want to do is implement onRetainNonConfigurationInstance() in your activity. This is called just before your activity is killed when the system knows it will be restarting it in a moment (e.g. for screen rotation).
Your implementation of onRetainNonConfigurationInstance() may return any object it likes ('this' is a good choice, or in your case, your cache). This object will be held and made available to the next invocation of your activity.
In your onCreate() method, call getLastNonConfigurationInstance() to retrieve the object the system is saving for you. If this function returns null, proceed as you would normally. If it returns non-null, then that will be the object you previously passed back from onRetainNonConfigurationInstance() and you can extract any information you want from it. This generally means that you don't need anything from the savedInstanceState bundle or from saved preferences.
I believe even open sockets, running threads, and other objects can be preserved across configuration changes this way.
Adding on: If you do pass this through onRetaineNonConfigurationInstance(), don't hang on to it. You'll keep huge amounts of resources from being freed. Extract the information you need and then release it.
You need to override your onConfigurationChanged event.
In my app I was playing music and when you flipped the phone it would stop and then I found out that if I overrode the config change I could just tell it to start my timer again and nothing was lost. I know this inst exactly what you wanted but it may help get you going in the right direction.
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
startTimer();
}
When you rotate the screen, you go through the activity lifecycle. The activity goes through onDestroy() and its onCreate() method gets called. You must redo any display calculations and view changes in onCreate and use the savedInstanceState to persist app data.
I hope this is what you were asking

Application lifecycle. How to run something only when application starts

I have a dialog popup to indicate how long I want an activity to run.
Seems simple enough, but its difficult to determine when the activity is really starting.
If the user opens the keyboard on a G1 and thereby goes into landscape, that reruns the activities onCreate method.
I can't have a static for the class or even create an application class, because I can't determine when the 'application' goes away. Even after destroying the only activity, the application is apparently still alive.
Is there a way to determine that onCreate has been called because of the keyboard being extended or landscape mode invoked?
Thanks
In onSaveInstanceState you could store a flag indicating if it had run. If the app was being restored then in onCreate(Bundle savedInstanceState), the savedInstanceState will have the variable so you could check if savedInstanceState != null and saveInstanceState.get("restoring") != null then don't show the dialog.
I tried creating an application subclass, but still I could not determine when it would go away.
I tried another approach.
I added in the manifest within the activity,
android:configChanges="orientation|keyboardHidden"
Then within the activity I added,
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
This results in my onCreate method NOT being called when the orientation changes or the keyboard is hidden. I'm not sure why my view still looks correct in either case, but it works great. In fact it even handle text typed into the displayed dialog. The text is maintained when the orientation is changed.
Is there a way to determine that
onCreate has been called because of
the keyboard being extended or
landscape mode invoked?
There is a way to:
1. Check if the keyboard is being extended
2. a way to check the current orientation (landscape or portrait)
Determining whether onCreate() has been called or not will require some work on your part. For instance, you can have a variable to flag completion of onCreate() and save it in Activity's state Bundle.
You can put a check in onCreate() to determine if this is a first run or a restart due to Configuration changes, by making some sense out of values from 1,2 and the flag.
This is just a suggestion; better solutions might exist

Categories

Resources