What I have:
I have 3 activities in my app with a basic nested structure:
Activity 1 --> Activity 2 --> Activity 3
Activity 2 contains data embedded in an ArrayList<CustomClass>. CustomClass extends application (as taught here) and Activity 3 uses this to modify the CustomClass data for Activity 2.
What I want:
When the user hits the Home button and then opens my App again later, I want to return to whichever activity was on the top of my stack. (I thought this is supposed to be Android default behaviour.)
It works fine on my Eclipse emulator but on both my Google Nexus One and Huawei Honour, the task is completely restarted.
I have tried setting my activities to run in standard, singleTop and singleTask launch modes. The best result I could get on the phones was to return to Activity 1 (which is just a form) and still display what I had entered into the text fields before creating Activity 2.
I did also notice that if I hit Home then check the Running Applications under Settings, my app is not listed. Maybe Android might be destroying my task and I need to save the activity state. But this doesn't make sense if I press home and immediately re-enter the app?
Advice is appreciated.
There is no guarantee that once you hit the Home button and your Activity goes in onPause() it will keep its state (even it it keeps the same state, there is no guarantee on the actual amount of time the activity will remain in memory). This depends on the device in particular and how it handles its internal memory. (see this figure which shows the Android Activity Lifecycle).
The best practice is to always save your state in the onSaveInstanceState method. This post provides a good and easy example on how to do that.
Related
When a user enters an activity on my app I want to perform some logic during onStart and possibly launch a second activity before letting the user see the first activity (think of this as a pin protected activity)
I have a small issue where the contents of the first activity are shown for a second before the second activity is started. This happens when the user uses the home button to get out and in to the app. Is there a way to prevent the first activity to be visible at all before performing the logic validation?
This is more of a "design" solution to your problem and not clear if it'll work for you. I had something similar in the app I'm working on. What I did instead, was to create an interstitial Activity that resembled the same starting state (i.e. not yet completely loaded) of the Activity (Pin-protected Activity in your case) that is about to be started. Once I'd made my appropriate decision about whether or not I could go on, I just navigated to that initial Activity. In your case, I could see you making the decision on this interstitial Activity, and then navigating to the Pin-protected Activity or to the other one if conditions were not met properly.
The only downside to this approach is that the app does a quick flash with the additional Activity, but I think the increased separation of logic is worth it.
I have an app in which I programmatically create an EditText view. I assign an ID to that view using setId()
myEditText.setId(100);
so that Android automatically saves that object's state when pausing/stopping the app (as I was advised to do here). It works in these cases:
(1) When I leave the app using the "Home" button: if I then come back to the app, the object's state (displayed text) is restored, as expected.
(2) On a screen orientation change (which involves Android automatically destroying the activity and restoring it through a Bundle). The object state is also kept.
However, it doesn't work in this case:
(3) When I leave the app using the "Back" button: if I then come back to the app, the EditText object is empty.
Any explanation as to why this happens? Does Android really distinguish between leaving the app with "Home" and with "Back"? According to the documentation, the object's state should be automatically preserved, through a Bundle, even when the activity is destroyed. And that clearly happens in case (2). But not in case (3)!
If this is normal behaviour, how could I have the app's state automatically saved and restored when the user presses "Back"? I know I could use the SharedPreferences for that, but I'd rather have Android do that automatically, just as it does in cases (1) and (2).
This happens at least in Android 4.0 and 4.2 (I haven't tested others).
You really should study activity life cycles as there are many many ways to solve the problem. Since your activity is typically pulled off of the stack and destroyed when you navigate back one quick but not necessarily the best way is to make sure your activity flagged as singleTop or singleInstance in the manifest that way it is not pulled off of the stack and recreated when you navigate back and forth. You could also use the singleton Application class. Or pass the text back and forth as params. Or use a database. Or use MVC or some other programming paradigm that will allow your views to be destroyed and recreated with out the data populating them going with it. Lots of "or's". Study activity life cycles and then look at how you have your application architecture setup already and choose the method that will work best for you.
http://developer.android.com/training/basics/activity-lifecycle/index.html
http://developer.android.com/guide/components/tasks-and-back-stack.html
I think I found the explanation. I only needed to read the doc more carefully (thanks to #lentz for one of the links); see here and here:
When your activity is destroyed because the user presses Back or the activity finishes itself, the system's concept of that Activity instance is gone forever because the behavior indicates the activity is no longer needed.
If the user presses the Back button, the current activity is popped from the stack and destroyed. The previous activity in the stack is resumed. When an activity is destroyed, the system does not retain the activity's state.
The above explains behaviour (3) in my question.
However, if the system destroys the activity due to system constraints (rather than normal app behavior), then although the actual Activity instance is gone, the system remembers that it existed such that if the user navigates back to it, the system creates a new instance of the activity using a set of saved data that describes the state of the activity when it was destroyed. The saved data that the system uses to restore the previous state is called the "instance state" and is a collection of key-value pairs stored in a Bundle object.
The above probably explains behaviour (1) and (2).
What I don't see is why the user pressing Back should be interpreted as "the activity is no longer needed" ("its state needs not be preserved"). But that's a different matter.
I have There Activities(A,B,C) within my Application.When i start the Application
Activity A:
A:onCreate()
A:onStart()
A:onResume()
Using intent i am calling Second Activity(A -> B):
A:onPause()
B:onCreate()
B:onStart()
B:onResume()
A:onStop()
Then I click the "Home" button So the App goes to background:Now
B:onPause()
B:onStop()
After 1 or 2 hour later Again i go to home page within my device and Click the App icon it runs like:
B:onDestroy()
A:onRestart()
A:onStart()
A:onResume()
But i need to go which one Activity i quit like this,
B:onRestart()
B:onStart()
B:onResume()
I have read some articles it says like that activity killed by the system because of no longer visible.Is there any possible to fix my issue...
Thanks in advance...
You may be confusing two different things here:
Android does not kill an activity if it needs memory. What it does is that it kills the whole process that the activity is running in. In general that means that Android kills all of your activities in this situation. However, it remembers the activity stack and when the user returns to the application, Android will create a new process and then recreate each activity (in turn, as needed). It starts by recreating the activity that was on the top of the activity stack (ie: where the user left the application).
Android assumes that if the user leaves a task for a long period of time (I think this is something like 30 minutes) then he is no longer interested in that task and there is no point in remembering where the user was in the activity stack of that task because he probably doesn't care anymore. In this case, what happens is that when the user returns to the task (or restarts the application that was on the top of the activity stack in that task) Android simply clears the task back to the root activity. This has the effect that it looks like the application is starting all over again. This is the desired (and documented behaviour).
What you want to do is prevent Android from clearing the task in situarion #2. You do it by adding
android:alwaysRetainTaskState="true"
to the <activity> tag of the root activity (ie: the activity that starts your application, the one with ACTION_MAIN and CATEGORY_LAUNCHER).
I don't believe this is something you can surely control. If your activity is in background for a lot of time and meanwhile other applications need memory, the system will kill your activity to free memory.
I am having trouble finding out how to maintain the state of my Android app in development.
Just to clarify, I am not talking about maintaining activity state (i.e. keeping track of textbox values, checkboxes, etc on a specific activity).
Let's say for example my application has two activities A and B. When I start my app, it takes me to activity A, and pressing a button on it takes me to activity B. At this point, I press the home button on my phone to return to the main Android UI and exiting my app . However, if I choose to run my app again, it should take me to activity B, which is where I left off before pressing the home button, but instead it is taking me to activity A.
Does anyone know how I can rectify this?
(I am using a Samsung Vibrant in case if you need to know)
"However, if I choose to run my app again, it should take me to activity B, which is where I left off before pressing the home button, but instead it is taking me to activity A."
Yes, it should. If it isn't, you have done something in your app to tell the platform to modify its behavior. (Look at ApiDemos as an example, it uses the standard behavior, which is what it sounds like you are describing as what you expect.)
Things to look out for:
Don't use FLAG_ACTIVITY_NEW_TASK when launching activities.
Don't use the singleTask or singleInstance launch modes.
Don't see the clearTaskOnReset flag.
You're imagining there's something called an "Application" but that's an illusion. Your application is just a collection of Activities, Services, Receivers, etc.
If you look at the intent-filter tags in your manifest, you'll see that each icon in the home screen is associated with a filter like this:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
You can put that same chunk of XML on both of your Activities, and you'll get two icons in the home screen, one that always launches Activity A, and one that always launches Activity B.
What you may want to do instead is create a master Activity that launches one of the other Activities based on the shared state.
As for where to actually store the shared state, that depends on how complex your state is. This is a good place to start: http://developer.android.com/guide/topics/data/data-storage.html
As I understand the question you want to launch your application and have a different thing happen each time depending on where you left off the last time.
http://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks.html The activity lifecycle is in the link. Your onActivityDestroyed method somehow needs to persist the present state and the oncreate needs to pick it back up. Persistence can be achieved via shared preferences, stored in a file, database or over the network http://developer.android.com/guide/topics/data/data-storage.html This unpredictable behavior could cause confusion for the end user if poorly implemented so use good judgement.
Trying to understand best practice for the lifecycle of my android application, and how activities fit into it.
For example, I have a main activity, sort of the "home" of my application. But, on start-up there are several activities that I 'might' need to run, depending on several cases, one being that it is the first time the app's been run.
Is best practice to call these 'start-up'/house-keeping activities FROM my 'home' activity? Or should the application begin with a 'house-keeping' activities, do the work, then finish() and start the 'home' activity?
Thanks for advice about this,
-- J
For the best user experience (and cleaner code), you really shouldn't chain Activities.
A good best practice for the scenario you describe (needing a particular layout of options on first-launch) is to set a SharedPreference the first time that the "Home" Activity is created. In the same Activity.onCreate() call you should make a decision about what your UI will display based on that saved value (e.g., either set the appropriate View's visibility to View.GONE or choose a different layout.xml altogether).
As an added bonus: You can overload a hypothetical "has been opened" SharedPreference with the version number of the app (e.g., LastOpenedVersion) to be able to present the user with a change log the next time they open your "Home" activity after an upgrade.
I would set your LAUNCHER <intent-filter> on whatever the user will most likely want to go to from their home screen. Presumably, that would be your "home" activity.
In onCreate() of that activity, make the determination if there is some other activity that is needed (e.g., "first-run"), and call startActivity() on it. When the user presses BACK from there (or you finish() that new activity), control will return to your "home" activity.
One possibility is to start from a splash screen Activity (rather than a "home" one), which then determines what to launch next.
You should also consider if your start-up/house-keeping needs to be accomplished via an Activity. If it is not something that the user interacts with, then you can move that functionality into a Service that runs a separate thread.