Android: onCreate() getting called multiple times (and not by me) - android

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.

Related

Launching an Android activity and act upon it once opened

I have this piece of code which basically should launch an activity and act upon it, for example, set its title :
void launchAnActivityAndSetItsTitle() {
context.startActivity(intent);
activityMonitor.getCurrentActivity().getSupportActionBar().setTitle(title);
}
The activityMonitor variable is a component which holds a reference for the current foreground activity.
It is set upon the onResume() of each activity in the app.
When I run this code, the activity launches only once this method is over, which makes the second command useless, as it sets the previous activity’s title, not the new launched one. Adding a delay before the setting of the title didn’t help.
When I debugged it, I saw that the the code of the second
command is consistently being called before the onCreate() of the required new activity (regardless of the delay I set between the two). My question is why.
Thanks
EDIT - My need better explained:
I know how to pass data to a new activity. I was interested in knowing the reason for this particular timing issue - why does the activity get always launched AFTER the end of this code block/method.
According to my design, this method resides in a separate module, which is only responsible for executing a url (which is turned into a specific intent, according to a url matcher), and allowing a callback to be called after the execution of the url, i.e. after an a activity is launched.
In this example, the callback is actually a call to a method which tries to set the current activity's title (the callback method resides in the app module and is passed to the "url executor" module as an argument).
So now that I explained my need of this sort of generic approach, maybe you could give me tips on how you would do it, without falling into this "activity didn't really launched yet" problem.
Thanks.
If you would like to modify something in the activity being started by the intent I would recommend passing an Extra along with your Intent and getting that extra in the new activity OnCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xxxxxxxx);
Intent i = getIntent();
setTitle(i.getStringExtra("title");
To put an extra inside an Intent use intent.putExtra("title", "newTitle");

(Activity recreation): what to do with a backstack built on invalidated data?

What to do when:
1. The app uses a complex structure of Activities and Fragments
2. I return to a backgrounded application that has been (partially or not) destroyed in the meantime
3. It returns me to the last screen, which lies deep in the workflow
4. I need it to return to the first screen to reinitialize things (because it's complex and requires user interaction)
Just to be clear:
I am asking how to deal with the existing stack(s) of Activities and Fragments upon encountering this situation.
- action to take: launch an Intent? Just finish? Do something to held substructures and then finish?
- when to perform it - immediately in both Activity.onCreate and Fragment's empty constructor? Or are Activities sufficient?
- How best to detect it: all I've come up with so far is: binding to a Service that holds the necessary data/connection, and then asking if it's been initialized. But the binding finishes AFTER onResume.
I am not asking about anything UI-related.
I am not asking for a solution that will only work for one specific application, so don't ask for code.
If you see this question as vague, here is a one-sentence version: "How to dismiss the stack and return to the first screen?"
For details (as much, at least, as are relevant), see https://stackoverflow.com/questions/14650342.
If you recognize that your application is in an inconsistent state and you need to start over, the easiest way is to relaunch your root activity like this:
Intent intent = new Intent(this, MyRootActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
This will clear all activities from the task and restart the root activity.
I would suggest doing this in onCreate() of activities.
when app is in the background and os wants to free some memory. whole PID is killed, which kills ALL activities. Docs are misleading about this behaviour. See this post
Android app out of memory issues - tried everything and still at a loss
where hackbod (Android platform developer) kind of confirms it.
When you have mulitple activities A,B,C and when your app is killed and you want to bring it back.
onCreate(not null) of most top activity will be called. Its worth noticing that when this scenario happens and you do something like
onCreate(not null){
startActivity(new intent)
finish;
two things will happen :
startActivity will launch new activity
finish will close current activity BUT it will bring back the previous activity (from killed pid) with its onCreate(not null) which simply was next activity in the activity stack.
This might cause multiple activity instances problems.
I had a similar problem some time ago, ended up with ugly hack but it worked :
to reinit whole app, I added something like
onCreate(not null){
if(launcher activity == null){
finish();
return;
in all activities.
Depending on what you want to achieve use flags as others have suggested.
Hope that gives you some hints.
If your goal is to dismiss all the activities and get back to your home/main activity then you can simply use:
Intent intent = new Intent(getApplicationContext(), Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
This will clear all the activities on top of home and return you to the home screen.

Android intent reception and rotation

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 :)

onDestroy() gets called when calling startActivityForResult()

I have a problem returning from the GPS Settings. I want to check if GPS is enabled, but for some reasons not only onStop() gets called from the calling Activity, but also onDestroy and when I return from the Settings I arrive at the Main Screen as the Activity has been destroyed. I don't know what triggers this behavior as in another App the same Code works and returns. Its a simple call :
case(GPS_SWITCHER):{
Intent intent = new Intent("android.settings.LOCATION_SOURCE_SETTINGS");
//intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivityForResult(intent,REQUEST_CODE);
}
I tried working with the flags for the Intent but that did not solve it. I also tried calling the Intent from a PreferenceActivity, but already this call kills the Main app :-)
Any ideas ?
Thank you !
check if you write noHisory="true" in activity tag of Manifest file and remove it .
also check for other inappropriate parameter .
You forgot break; in your case statement. That means the code immediately below is executed too.

added TextToSpeech to my activity and now my onDestroy is not called any more, bug?

I added TextToSpeech to my app, following the guidelines in the following post:
http://android-developers.blogspot.com/2009/09/introduction-to-text-to-speech-in.html
and now my onDestroy is no longer called when the back button is pressed.
I filed a bug report regarding this: http://code.google.com/p/android/issues/detail?id=7674
Figured i should also ask here if someone else has seen this, and found a solution?
It seems that it is the intent that causes the problem, i.e. the following:
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
If I skip this intent, and just go ahead and create a tts-instance, it works fine.
Any clues to what is wrong with this intent?
Think I've figured this one out.
My problem is that I was assuming that onDestroy would be called when my activity finished, so that I could store the state (and preferences, et c). And I assumed that onDestroy would always happen before a new instance of the activity was created, so that the new instance in onCreate could load the state stored by the old instance.
This does not hold in general. It does not even hold true for onStop.
The solution for me was simply to save what I wanted in onPause. It seems I can count on this one being called before any new instance can be created. But since onPause is called in many cases where I don't need to save, I also check isFinishing(). I.e. if isFinishing() in onPause, then I save.
Note that it didn't seem to matter if I launched my activity in singleTop mode, I would still get two "alive" instances. One which was on its way to being destroyed (onPause was called but was yet to enter onStop or onDestroy) and one which was in onCreate.
Anyway, I hope I've solved it now.
Reproduced.
It appears that the key is where you call your initTTS() method (or equivalent) from.
If it is called from onCreate(), I also see the behaviour above (onDestroy never called).
Hinted by the doc for startActivityForResult (where calling from onCreate is a special case), i tried invoking the intent via a delayed message to my own Handler.
Now, onDestroy is called again!
(also commented this on your bug report)

Categories

Resources