Clear back stack when application object gets killed by the system - android

I have an application with a lot of activities. Among them there is InitialActivity which loads the core data. It's a launcher activity and none of the next activities can live without the loaded data.
So I launch the app, the InitialActivity is loading data, then navigates to the MainActivity and then I'm browsing to some FarAwayActivity. Then I'm switching to other apps (some of them are heavy games) and my application is getting killed on the background. I've inserted log call in my Application.onCreate() and I can see that it's called again, when I switch back to my application. So I'm sure that the app is killed on the background. But Android brings the very last FarAwayActivity to top and it crashes immediately because all the loaded data are nulls.
So the question is: how can I tell the application to start over from the InitialActivity when (and only when) it's getting killed and restored? Something like "forget my back stack", but presumably automatically, in the manifest.
I've already read and tried everything from Activity tag docs, but nothing matches my expectations. The closest thing is android:clearTaskOnLaunch="true", but it clears all other activities on the stack when relaunching app from desktop (and app isn't killed yet, so all the data are available). To be clear, I want to start with InitialActivity only after the app was actually killed.

First I would suggest you to instead of storing it in the Application, you could pass your data to your Activity through Intent.
This way when the Activity get restored, the saved Intent will bring its data back.
Now to a suggestion to your actual question:
When your Activity gets restored, you will check if your data in the Application object is null
if they are you should call this:
Intent newIntent = new Intent(FarAwayActivity.this, InitialActivity.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
Now it should clear the stack till find InitialActivity.

Related

How to get previous Activity from PreferencesActivity?

So, I have a feature in PreferencesActivity and I need to get the previous activity, which is still running, e.g. when you access directly the preferences while still at this same activity. So it is still alive.
I tried through casting and context, which would be have been useful, if I had any other except AplicationContext and BaseContext.
So is there a way to get the previous activity from preferences activity?
which is still running
Not necessarily. The user can press HOME (or switch to another task via the overview screen), then return to your app several minutes later. If your process was terminated in the meantime, the user will be returned to a newly-created instance of your preference activity, but none of your other activities will be running.
This is why communication between activities is loosely coupled.
So is there a way to get the previous activity from preferences activity?
Nothing that is supported and will work all of the time.

Prevent activity from being destroyed as long as possible

I have an app, a single activity app with fragments in it.
The usual use case for this app is, that you start it and put the phone away and every now and then, you get back to the phone and insert some data... It's a logging app, you are doing something and insert your results into the app...
I have the problem, that every now and then, my activity get's destroyed and is recreated with an empty bundle... (Most of the time this is not the case, but every now and then this happens...). My app sometimes starts a service, even this service is killed in this case...
This means, that the system has killed my app, does it? How can I avoid this?
I need to keep the user data and the current top fragments... And they are saved to the bundle and everything works as long as their states and the data get saved...
Btw., my activity is always the TOP ACTIVITY, only that the screen turns off often... I just want to keep my activity alive as long as possible until the user leaves it with the back button... Or to save the state reliably
IMPORTANT NOTE
onSaveInstance does not always work (it's not part of the lifecycle and therefore not guaranteed to be called)... it only works most of the time... I need a way to that works always... If android kills my app...
don't keep your app in memory
You don't want to block Android from killing your app. What you want is to restore your app's state properly. Then the user will never notice the app has been destroyed and the user still gets the benefit of an app that was destroyed when not in use.
If you really want this use a wakelock. This will drain your users battery so I think twice before implementing this... Info at How do I prevent an Android device from going to sleep programmatically?
onSaveInstanceState explained
To do so check what information is needed in the bundle and persist that information with the onSaveInstanceState(bundle:Bundle) method so you can reuse it in onCreate(sameBundle:Bundle).
More information available from Google documentation at Save your Activity state and Restore your Activity State.
About Android Activity lifecycle
As stated by #prom85 in the comments below it's not guaranteed that the onSaveInstanceState method will be called because it's not part of the lifecycle. Workaround for this is using the onPause lifecycle hook to ensure your data is stored.
More information at Android: onSaveInstanceState not being called from activity
I had a similar problem, I arrived at this post while searching for a solution, you have to play with the manifest to achieve this and also understand what exactly activity is, in Android eco system,
In Android activity is a task which has a pre defined work.
I dig a lot in the documentation, I found that, we can configure activity in two ways,
Persistent
non persistent
if you mention for the activity in the manifest as
android:persistent="true"
and run the below use case
Start the APP
Press back or home button
you select the activity in the back stack again to bring it to front
Activity enters start -> pause -> stop - > resume , it does not get into onDestroy method.
if do not mention
android:persistent="true"
for the same use case
Activity enters start -> pause -> stop -> destroy, and if you select the activity from the back stack
Activity enters resume->create->start
If you want to run a service/task on activity start which keeps running when the app is in back stack, then you have to start that in the onCreate method, and kill them onDestroy by specifying your activity as persistent in manifest.
I hope my above solution might help others who arrive here for the same problem

pressing home button and access app again from app icon call onCreate?

I have an offline-online application, i found a strange issue in it, may be it is not, but i did'nt understand about it..
App requirement is that, if internet is available, even from starting app or from resuming, i call webservices and store data in sqlite, otherwise app stays in offline mode,
I have 2 activities, second activity contains an id, that i passes through intent (that point is important),
My Problem:
if i am in second activity, and internet is running, and i press home button , then this 2nd activity pauses, then stop which is a default behavior in android, i goto settings, turn wifi off, then press app icon again to get back in my app, here i got confused, i expect that my app now will be in onResume, but when i see in logcat its onCreated called and app
crashes, nullPointerException occurs, because this 2nd activity does not have that id, i passed through intent..
Note:
If i use recent app button to go to "settings", then come back again after turing wifi off, and repeat all this behavior, then working fine, its onResumes called not oncreate..
My Question
Why it is going in onCreate while i my expectation is to be onResume while i came back from app icon?
The NPE reason is clear, your second activity doesn't have the value and it crashes.
Why do you get different behavior then!?
It's because the launching intents are different. When you "task switch" Android is merely stopping your app but leaving it there (no guarantee) in case you want to switch back.
Going home (with home) is a clear indication that you want to leave the app, and although it will remain in memory and cached (as long as there is available memory), going back through the launcher (or App Icon as you call it) fires the LAUNCHER category (which goes to your Activity 1 first).
Take a look at this StackOverflow question (and answer) to better understand the consequences.
In any case, your problem is that your app must always be designed to resume in an inconsistent state and be able to recover. Android will kill your references, will destroy your variables and most likely send your app to hell overnight even if you have it running… if the phone goes on standby, chances are processes that aren't doing anything will be paused/stopped and likely killed.
Re-design your app so this is not a problem.
You say:
"I have 2 activities, second activity contains an id, that i passes
through intent (that point is important),"
Well, why not make it easier and have ONE activity and TWO fragments? Then use Fragment Arguments to pass the value?
Or why not store the value in the preferences and/or a local database and recover it during onCreate?
And also why not make it so that if Activity 2 doesn't have a value, it calls Activity 1 and closes itself (better than a crash, huh?).
Etc.
As you can see there are multiple things you should consider. All in all, never trust that your app will be alive, because it won't.
Once your activity's onStop gets called it's susceptible to be killed by the android system to collect resources for other apps which is what i think happened in your case.If it is killed, android will obviously call OnCreate when you get back to the activity.Check this for clarification. For experimenting you can try opening more than one apps from your recent apps and then return to your app. It may crash there too now.
You stated that you can see that the activitiy is stopped (onStop) if you go to the settings. That is the behaviour shown in the Android activity lifecycle. The counterpart for onStop is onCreate. So it does what the documentation tells us. Btw activities are paused if they are visible in some way and get stopped if they are not visible anymore. This would explain why your activity get paused. For further information read Managing the Activity Lifecycle. You can find a whole picture of the lifecycle here.
This type of behaviour can be seen when you change some system configurations like font type,font size or language. But turning wifi on/off won't destroy the app and recreate it again. Check http://developer.android.com/guide/topics/manifest/activity-element.html#config for more information

onSaveInstanceState()/onRestoreInstanceState() in large application

I've got a complex application: an Application class and a bunch of Activity classes started as Intents from a common Activity.
According to the logs, the process is dying. It happens when I run my app, hit home, start up a whole bunch of other apps and then return to my app.
In the log, I see:
10-25 12:11:08.195: I/ActivityManager(2492): Process my.awesome.app (pid 20860) has died.
my.awesome.app then goes thru the onCreate() method of the main Activity as the app restarts.
However, I end up at the wrong screen because the instance variable that would direct me to the correct screen is not retaining the value it had when the app died. Actually, I'm hoping the app didn't die so much as it was killed by the system and then brought back to life.
Looking at the code, I see no onSaveInstanceState()/onRestoreInstanceState() methods so I'm pretty sure I need to provide them.
The question is which Activities need to provide onSaveInstanceState()/onRestoreInstanceState()/react to what they've done?
Let's say I'm a couple of Activities deep - that is, my Application class has started an Activity class that started a Thread to run an Activity and itself is running another Activity via an Intent.
Do all the involved classes need to provide/react to onSaveInstanceState()/onRestoreInstanceState()? Is it just the Application class since that's where I'm detecting the improper value that sends me to the wrong screen?
onSave/onRestoreInstanceState isn't really for application wide settings. It's more for settings particular to a single activity.
If you always want to go back to a certain activity after a process has been killed, you should probably save the last open state into a preference, and then in onCreate of your main launcher activity, launch the desired activity based on the value of the saved preference.

Retain data in WebView (Android)

I have various pieces of generated HTML/JS that I load into Activity with WebView#loadDataWithBaseURL. Is there a way to not load in again and again during Activity lifecycle? For example - user goes to check the message and then calls the app again. At that point - the Activity is stopped and probably destroyed, when it's loaded again I do not want to hiccup on loading the content user was already viewing.
For example - user goes to check the
message and then calls the app again.
At that point - the Activity is
stopped and probably destroyed
If the user directly visited the Notification, or clicked HOME, your activity is stopped but not destroyed. In these cases, your WebView should not change content unless you change it.
Your activity will be destroyed if the user presses BACK, or Android needs to close you out because of memory constraints.
In the BACK case, the user is expressly telling you to go away, so reloading your data seems reasonable.
In the memory-constraint way, by definition the device is short on memory, so you're going to need to reload the data if and when you are brought back to the foreground.
When i click HOME, and later i restart my app, the content of WebView retained.
But when i trigger a Intent(such as barcode scanner), after the Intent finished and come back to my app, the WebView in my app was reloaded.
Could i keep my WebView content when the Intent returned?

Categories

Resources