I'm using an Intent Filter in my activity to retrive an url clicked on by the user.
In my activity onCreate method I have the following code
Intent intent = getIntent();
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
url = intent.getDataString();
showDialog(DIALOG_ID);
}
It works great except when I rotate my phone. Even if tha dialog was closed prior to the rotation, it reopen every time I change the phone orientation.
I can I avoir that.
For your information I don't want to lock the orientation
Another solution that doesn't require handling configuration changes yourself might be to simply check if the savedInstanceState Bundle parameter in onCreate is null before showing the dialog.
If you look at the docs for onCreate you can see that savedInstanceState will be non-null when the activity is recreated (due to configuration changes for example) and thus will be null when the activity is run fresh.
You would typically call setIntent(null) to remove the intent used to summon the activity. However, in practice, it doesn't always work. Apparently, a common workaround is to set the intent's action or data or both to null, depending on what you use in code. In your case, after showing the dialog, I would probably go with intent.setAction(null).
This is a pretty simple fix. In you manifest file, locate activity and add this:
android:configChanges="keyboardHidden|orientation"
This will prevent your logic in onCreate to fire again (or so I believe)
Quoted from here:
In some special cases, you may want to bypass restarting of your
activity based on one or more types of configuration changes. This is
done with the android:configChanges attribute in its manifest. For any
types of configuration changes you say that you handle there, you will
receive a call to your current activity's
onConfigurationChanged(Configuration) method instead of being
restarted. If a configuration change involves any that you do not
handle, however, the activity will still be restarted and
onConfigurationChanged(Configuration) will not be called.
I have never seen this issue until today. I did getIntent().setAction("");, and solved it. No more brain damage :)
Related
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 :)
in my application (minSdkVersion 17, but I am flexible concerning this), I have a single activity. It displays some kind of timetable. I want to let it show the current day and scroll to the correct time.
This functionality is already working perfectly fine.
I want to do this everytime when the app is started, or everytime when the app becomes active again (e.g. after pressing the home button and just clicking the app icon again without killing the app inbetween).
But I do NOT want to do this, when the device is rotated.
For example, I have a method:
private void scrollToNow() {
// do the calculation and scroll all views to the correct position
// this is code I already have fully functional!
}
And I want to execute it every time the activity gets active again, but NOT on orientation change.
I tried a lot of combinations (in onStart, onResume, onCreate), but none of them did the trick. I tried to build a solution using the savedInstanceState but failed.
Anybody got some tips or useful links for me?
Thanks alot,
Oliver
Please, think twice before you decide to check configuration changes manually.
If your application doesn't need to update resources during a specific configuration change and you have a performance limitation that requires you to avoid the activity restart, then you can declare that your activity handles the configuration change itself, which prevents the system from restarting your activity.
Note: Handling the configuration change yourself can make it much more difficult to use alternative resources, because the system does not automatically apply them for you. This technique should be considered a last resort when you must avoid restarts due to a configuration change and is not recommended for most applications.
Try to save some flag in onSaveInstanceState and in onCreate check if there is savedInstanceState, then save it as field for example. This will give you information about does activity is 'recreated' or not. Then in 'onResume' check is this flag set or not. If not, then you are not 'recreated' your activity, so you can invoke scrollToNow()
I dont want to recreate layout when screen orientation change
Did you tried to add this line to your AndroidManifest.xml android:configChanges="screenLayout|screenSize|orientation" like that :
<activity
android:name="youractivity"
android:configChanges="screenLayout|screenSize|orientation"
android:label="#string/title_activity_create_note"
android:theme="#style/AppTheme"
android:windowSoftInputMode="stateAlwaysHidden" />
For more information you can take a look at : manifest/activity-element in that page go to android:configChanges section and read please .
When adding this you must handle onConfigurationChanged() method by yourself instead of Android System.
Please read carefully Note section in that page :
Note: Using this attribute should be avoided and used only as a last resort. Please read Handling Runtime Changes for more information about how to properly handle a restart due to a configuration change.
Also i am using this in my application maybe you can try this too : android:screenOrientation="nosensor" in that page you can find information about it too.
I have a MainActivity class, which launches a RaceActivity at some point. If, later, the RaceActivity exits, I want the MainActivity to return, with all its views. However, it seems to be created anew each time. I have implemented the proper section of onOptionsItemSelected, but when I click the back button, I get a new instance each time, or at least the programmatically added views are gone. What can I do to fix this?
Edit for clarification:
I am fine using onCreate with a bundle to restore these views, but I thought that happened automatically if you recreate the same instance of an object. I want to keep programmatically created views when the activity is recreated. Alternatively, I want the activity to stop being destroyed when the user returns to it. (I tested, and it gets destroyed as soon as the use returns.)
Accept my answer if it helps you. it take hours to find the solution..
override onBackPressed()
Intent intent = new Intent(FromAnyActivity.this, CurrentActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
and insert the code in it.. It will reorder your Activity from stack and your views and data will remain where it was. There was another way by adding SingleInstance launch mode.. read these link may help..
Add the following to your MainActivity declaration in the AndroidManifest file:
android:launchMode="singleTask"
According to the Android APIs, this addition is for: "The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one."
If the above doesn't work, I believe you can also try adding this as well to the MainActivity in your AndroidManifest file:
android:alwaysRetainTaskState="true"
According to the Android APIs, this addition is for: "Whether or not the state of the task that the activity is in will always be maintained by the system — "true" if it will be, and "false" if the system is allowed to reset the task to its initial state in certain situations. The default value is "false". This attribute is meaningful only for the root activity of a task; it's ignored for all other activities."
I am using start activity for result to help users of my application filter some information out. Once the information is filtered i add it to the intent and then call finish. The works perfectly except for when the users have rotated the device when they are performing the filtering. This causes the first activity to create all over again and since this happens my filtering options are wiped out (They finish before onCreate is over so the UI is cleared). Any ideas on a way to handle this?
Thanks
There are 3 options to do this
onSaveInstanceState() // But can usually handle small amount of data
onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() //Preferred
android:configChanges="orientation|keyboardHidden" in AndroidManifest.xml
// This will not let the activity to get restarted, use this when the data you want to conserve is not large.For api 13+ use this android:configChanges="orientation|screenSize"
There is something I don't quite understand right now.
My main activity class creates a Service, which creates a new thread that waits for a TCP connection. Once one comes in, it will start a new activity:
Intent dialogIntent = new Intent(getBaseContext(), VoIPCall.class);
dialogIntent.putExtra("inetAddress", clientSocket.getInetAddress());
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);
After that, the onCreate() method of that class gets run. It will create 2 threads: one records and send data, the other one receive and plays data. Those threads have a forever while loop.
For some reason, I notice that the onCreate() of that last class gets called again, which makes my program crash. I do not understand why it is called again as only the 2 threads are running, there is no user interaction. The documentation says: "Called when the activity is first created.". The activity is already running and I am not trying to create it.
Could someone please explain me this behavior?
Android will recreate your activity after certain "device configuration changes". One such example is orientation. You can read more here...
http://developer.android.com/guide/topics/resources/runtime-changes.html
Perhaps something in your threads is doing something which is considered a configuration change?
If that's the case you might find it useful to extend the Application class instead and do your initialization there. See this post...
Activity restart on rotation Android
HTH
I was experiencing an Activity called twice on some Samsung devices. I solved it adding android:launchMode = "singleInstance" on the Activity tag on Manifest. I hope this can help.
Similar to this question where orientation change is causing the device to reconfigure:
Activity restart on rotation Android
My preferred answer:
https://stackoverflow.com/a/11811999/3739540
Instead of trying to stop the onCreate() from being fired altogether, maybe try checking the Bundle savedInstanceState being passed into the event to see if it is null or not.
For instance, if I have some logic that should be run when the Activity is truly created, not on every orientation change, I only run that logic in the onCreate() only if the savedInstanceState is null.
Otherwise, I still want the layout to redraw properly for the orientation.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_list);
if(savedInstanceState == null){
setupCloudMessaging();
}
}
This happened to me once when I used "Don't save actions" in the app section of the developer options. Be sure you have turned this off.
I have observed this issue when you are trying start an activity with values in the intent.
Below is an example where Activity_A calls Activity_B and passes values in the intent to be collected in Activity_B:
Intent intent = new Intent(this, activityB.class);
intent.putExtra("val1", someValue1);
intent.putExtra("val2", someValue2);
intent.putExtra("val3", someValue3);
this.StartActivity(intent);
In this case, you can set the android:launchMode="singleInstance" or android:launchModel="singleTop" in your AndroidManifest.xml and Activity_B will only launch once. Hope this helps.