I need to launch the same instance of an activity even if the user goes back and forth with the navigation. The user navigates in a stack of different activies (A, B, C), but when he goes to one of these activities it will show the same instance of that activity (like a static activity) calling only onResume.
You can't force your Activity to start up in onResume(). What you can do, however, is save your Activity's state to a Bundle in onPause() and onStop(). Then, in onStart() read this Bundle to get your Activity's state.
The closest you can get to this is to use FLAG_ACTIVITY_REORDER_TO_FRONT in the Intent you use with startActivity().
However, this will call more than onResume(). At minimum, your activities will be called with onRestart() and onStart(), assuming that whatever was in the foreground took over the whole screen.
Related
Why is onSaveInstanceState called when starting new activity with startActivity(intent), but when user presses back or home from new activity, onRestoreInstanceState is not called?
When you navigate from Activity A to Activity B, Activity A will have its onSaveInstanceState() method invoked in case Activity A is destroyed (because the system needs to free up resources).
When you navigate back from Activity B to Activity A, there are a few different paths the code can take. If Activity A is still up and running, it will simply resume (and you'll see onResume() called). If instead Activity A was destroyed by the system while you were on Activity B, Activity A will need to be recreated. You'll see onCreate() called by the system (and its param savedInstanceState will be non-null and populated with what you put into it in onSaveInstanceState()) as well as any other lifecycle methods that happen "after" onCreate().
I wrote an Android app with several Activities and a Main Activity. When I go from the Main Activity to lets say Activity B, I want to "pause" the Main Activity, when the back button is pressed it should go back and reactivate the Main Activity instead of calling onCreate().
This shall work with all Activities, so if I click on a button to start Activity B, it shall also reactivate the old Activity B instead of creating a new state with onCreate().
How can I realize this?
PS: I already tried it with parcelable, but this do only work, if I close the application or something unexpected happens.
It's always possible that the first activity may be destroyed when you start another activity. It will be recreated when you go back to it. Every app should be written with this possibility in mind. To make sure your activities can handle being destroyed and recreated, turn on the "don't keep activities" developer option.
It is by default in Android. If you Start Activity B from Activity A then activity A goes in stopped state. Below methods will be called of Activity A
onPause()
onStop()
When you tap on Back key on Activity B. Below methods of Activity A will be called.
onRestart()
onStart()
onResume()
For reactivating Activity B, you can set Activity B launch mode as singleInstance. This will make sure that only single instance of Activity B will be created. onCreate will be not be called again. onNewIntent will be called when that activity is reactivated.
Refer: http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
Activities live in stack order. Each activity has its life cycle. When you close an activity (Activity B in your example) it eventually reaches onDestroy() method and removed from the stack order. It is by default in Android and there's nothing you can do about it.
What you can do is rewrite the onStop() method in Activity B and save some activity data (like text in EditText, for example) in SharedPreferences - read here. Then in your onCreate() method you can call for SharedPreferences, check if it's not empty and restore the text in the EditText by pulling appropriate value by key.
I am little confused between the life cycle of two activities.
Suppose I have Activity A and Activity B.
B is called From A i.e A ----> B.
Now currently B is on the screen and I pressed back button. Here I want know:- is there any memory still available for B(Active) or B's memory is flushed(Inactive).
The following activity call back methods are called, after pressing back button.
onPause()
onStop()
onDestroy()
The activity is destroyed.
And it recreates when launched again. These are the callback methods when it launches again.
onCreate()
onStart()
onResume()
I know the answer is been accepcted, still if this helps someone I am putting it.
When app is opening for the first time, by clicking the Icon
onCreate()
onStart()
onResume()
When home button is pressed
onPause()
onStop()
when app is again opened by clicking the app icon or launched from recent
onRestart()
onStart()
onResume()
when app is opened and then back button is pressed
onPause()
onStop()
onDestroy()
The onDestroy method is called after back press. Then activity will be popped from the Activity back stack.
From docs:
If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing its process. When it is displayed again to the user, it must be completely restarted and restored to its previous state.
onDestroy() from docs:
The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.
Activity B will be destroyed and will no longer remain in memory.
For more information please visit the official documentation for android and have a look at the activity life cycle figure.
Once you press the back key the activity's onDestroy() method will be called and the activity will be flushed out of the memory. You will then be required to restart the activity by calling the startActivity() method which will in turn call its onCreate() Method.
I would suggest to refer following link for activity lifecycle
http://stackoverflow.com/a/8516056/3110609
and following link for launch mode of activity.
www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode
After pressing the back button, Activity B will b destroyed. You see, Android Manages Activities like a Stack(an explanation of a stack). Everytime you start an activity, it pushes into the Activity Stack. So when Activity A calls Activity B, Activity B is now on top of Activity B, and when you press the back button, it also does a pop in the Activity Stack. So in concept, Activity B is gone. Pressing a Home Button is different from pressing back, it pauses the Activity, therefore it still eats a little of the phone's memory.
Here is a good explanation of how Android Manages Activities.
I have 2 activities (A and B) and they have 2 buttons to switch between.
A oncreate
B oncreate
A oncreate
A onresume
what I wanted to do is after sending intent from B to A oncreate should not be called but at this point it does. To overcome that I found FLAG_ACTIVITY_REORDER_TO_FRONT (from here) and thought it could called only onresume but it didn't.
FLAG_ACTIVITY_REORDER_TO_FRONT does exactly what you think it should do. However, if you start ActivityA and then ActivityA starts ActivityB and calls finish() on itself, then when ActivityB starts ActivityA with an Intent that has FLAG_ACTIVITY_REORDER_TO_FRONT there will be no instance of ActivityA to bring to the front. In this case Android will simply create a new one. I can only assume that is what you are seeing.
FLAG_ACTIVITY_REORDER_TO_FRONT changes activity history. If the requested activity is found in the history of previously visited activities (in a task), the older history record for this activity is cleared. So, while pressing back button, user will not encounter this activity in a task.
This flag won't affect the call to onCreate(), If activity does not exists in the task (not loaded or destroyed), onCreate() will be called to create it.
You can't just cancel onCreate. If B is full screen activity android can kill A activity and will recreate it when you try to restart it with FLAG_ACTIVITY_REORDER_TO_FRONT flag and call it's onCreate method. If Activity A will be still alive at the monent when you try to bring it to front, onCreate method should not be called.
Maybe in your case you should try to use fragments?
Is there any way to tell whether an Activity is being resumed (i.e. onResume is called) from the home screen/launcher?
For example, if I have an Application with two activities, A and B.
Scenario 1:
Some user action on Activity A will invoke Activity B, bringing it into the foreground - moving Activity A into the background. As Activity A moves into the background, it goes through onPause() and onStop(). The user (now on Activity B) either finishes the Activity or hits the "back" button, bringing Activity A back to the foreground, causing an onRestart(), onStart(), onResume() sequence.
Scenario 2:
If the user hits the "home" button while Activity A is in the foreground and then re-invokes the Application from the launcher, it goes through the same lifecycle as in Scenario 1. I.e. User hits the "home" button. Activity goes through onPause() and onStop(). User launches the application again, causing Activity A go come back into the foreground, again going through the same onRestart(), onStart(), onResume() sequence as in Scenario 1.
As far as I can tell, the Activity has no way of knowing how it was resumed, it just knows it is being brought back into view. In fact, I have a feeling that there isn't really as much of a concept of an "Application" in Android - in the sense of something that has a single entry and exit point.
in Scenario 2, your activity will get an onNewIntent call, with the launcher intent passed to it.
You could capture the back button press on Activity B and pass an extra value to Activity A. If there is an extra value then the activity was resumed from pressing back on Activity B, if there is no extra value then the Activity was resumed from being hidden.
Could Acitivity A use startActivityForResult() to start Activity B and use onActivityResult() to detect that Activity B finished?
So the straightforward answer to the initial question is probably: no. Launching an activity from the home screen through an icon, or resuming it from the recents screen can not be observed from the intent it is (re)started/resumed with.
Depending on what you are trying to achieve there are some approaches though:
what #superfell suggested:
Check for whether the onNewIntent-method is called on your activity to decide if it was restarted from the launcher. As a precondition you need to set your activity to singleTask/singleTop launchMode in your Manifest:
android:launchMode="singleTask"
depending on what you're trying to achieve, this might be enough! But additionally you might have to deal with what happens when the user presses the back button. Default behavior is to finish & destroy your activity. Thus a brand new copy of it would be launched when it gets selected from the recents screen. Though onNewIntent would not be called, everything would be rebuilt from scratch. If you need to prevent this you can use:
override fun onBackPressed() {
moveTaskToBack(true)
}
finally when you navigate "back" from an activity you launched yourself onNewIntent will also not be called. If you further need to distinguish why your activity is resumed, you might want to start the 2nd activity with startActivityForResult so the onActivityResult is called when you get resumed.
Launcher activity & Intent extra
A completely different approach would be to have a "launcher" activity in your manifest that directly calls your "main" activity and finishes itself. When calling your main activity you can put an intent extra that allows your main activity to distinguish if it was just launched for the first time, or not. As the extra would be present on further onResumes, make sure to overwrite it the first time you "consume" it:
override fun onResume() {
super.onResume()
val firstLaunch = intent.getBooleanExtra(FIRST_LAUNCH, false)
intent.putExtra(FIRST_LAUNCH, false)
if (firstLaunch) {
// do something
}
}
and when starting from your "launcher" activity:
intent.putExtra(FIRST_LAUNCH, true)
startActivity(intent)