What causes this weird app life-cycle? - android

My Android app checks if a specific service is not running, in my Activity's onResume method. If it hasn't been started, then it goes into the background (via startService) and stays there for an action. Clicking on a button causes the service to go into the foreground and it works great. Now the problem:
Scenario #1 :
The foreground service has a button, which sends it back to the background and stops it. I click on it and after that I close my app (the activities from the recents view). Even the Android monitor shows me that it's not running and works as it should.
Scenario #2: (The not expected behavior)
First I close the app (the activities) and then I click on the service's close button. In this case, I can clearly see that my app still uses the same amount of memory it used while the activities were opened. When I reopen my app, I can see that it continues working where I left it (at least the internal app variables don't get garbage collected) Sometimes the CPU usage monitor shows that methods get called, but not from my app. Only Android SDK functions. I couldn't see objects kept in the memory, but a lot of chat[], String, FinalizerReferences etc...
What could cause this? Ruined context lifecycle? Memory leak?

Related

Why can't app start from recents if paused too long

I've noticed an issue when I pause my app, say by pressing home, and then bring up the list of recent apps (via the square button) to resume it.
If I resume it shortly after pausing it, it works fine. But if I leave it paused for too long, i.e. a few hours or overnight, then when I touch its window to resume it, it just posts a "failed to start..." toast and removes the app from the list.
I've searched around, but haven't found any info about what would cause this or how to start debugging it.
My theory would be that is has to do with the activity lifecycle. You can find it here:
https://developer.android.com/training/basics/activity-lifecycle/starting.html
When an app is paused, the onPause() function is called, and if the app is paused, and the system needs memory for another app that is running in the foreground, it will stop, or destroy the activity. When you go back into the app, it calls the onCreate() and onStart() functions
I don't know how your app is structured, but my guess is that when the activity is stopped, it is leaving behind some kind of code that needs to reference something that is no longer there, or destroying the referenced thing itself. Then, when onStart() is called, it checks for that thing that is no longer there and crashes.
The best way to fix this is to make sure that each step of the life cycle isn't referencing anything that could possibly be non existent at the time it is called.
When the user leaves a task by pressing the Home button, the current activity is stopped and its task goes into the background. The system retains the state of every activity in the task. If the user later resumes the task by selecting the launcher icon that began the task, the task comes to the foreground and resumes the activity at the top of the stack.
If the user leaves a task for a long time, the system clears the task of all activities except the root activity. When the user returns to the task again, only the root activity is restored. The system behaves this way, because, after an extended amount of time, users likely have abandoned what they were doing before and are returning to the task to begin something new.
You might look up into the Android documentation regarding Tasks and Back Stack and upon some information about Pausing and Resuming an activity. :)
You issue probably related to memory management on android. It looks like android kills you app to release memory so that it can be used by another app. I have an app with very complex layout (The app loads too many images). After some times, when I run the app from recent app list, it always run the app from start. Not from the last state where I left the app. Anywa, nothing to worry about. This is normal behaviour.
As of my concern this is your problem-
you are starting an activity.
then you press home button. and the activity goes to background.
when you start the app after 5 minutes the app starts from the paused activity. but when you start app after 5 hours the app starts from the beginning.
Solution-
This is happening because the activity is being killed in background by the android system.
the application can be killed by calling the ondestroy() method of the activity.
and when the app goes to background it is added to the application stack of the android system. when ever android needs more memory for any operation it takes memory from the last application in the application stack. it kills the last application and takes its memory.
this is the reason your app is being killed after long time. your app is at the last of the stack and android has killed your app to get memory.
you can find more explanation of the process here.
How to solve this problem
this can be solved by bringing your app to front of the stack periodically.
you can run a service from your activity in background so that is stays on top side of stack.
or save the last opened activity in a shared preference and go to this activity when the app starts.

Differentiate between Android killing the app and user swiping it off on the recent apps list

I am working on a project, where while being on a specific Activity we show a local sticky notification. That should also be the case when the app is minimized. What I have to accomplish is to remove the local notification whenever the app is killed (by Android, because of memory lack or by the user, with a swipe from the recent apps list).
Usually onDestroy would be called whenever Android takes the Activity to open some space. That is fine in one of the cases, however swiping an app from the recent app lists doesn't call the onDestroy and the sticky notification stays.
What I did is, I implemented an empty Service which would force the onDestroy when the app is killed (both swipe and system kill) so I can get my notification removed.
However, what I would like to do is to differentiate between the swipes and system kill.
Is this even possible?
In general, if Android wants to kill your application because it has been in the background for too long (or because it wants to reclaim resources), Android will just simply kill the OS process hosting your app. It will not call finish() or onDestroy() on any Activity or Service components. The behaviour of "swipe from recent tasks list" has changed over time and is different in different Android versions. Someone should write a book about that :-(
You can check for when the user swipe-closes the app by adding a service to your app, and implementing the onTaskRemoved method: https://stackoverflow.com/a/26882533/2441655
This is a comment I found in reddit that seems to me really interesting:
Swiping an app away will effectively "kill" most apps. You can test
this out using ADB if you have the SDK installed. Swipe everything out
of your recents list, then launch the browser.
Use ADB to run 'ps' on the device and verify that the com.google.android.browser process is
running. Go to the home screen, it's still running. Launch some other
apps, and the com.google.android.browser process is still there.
Swipe it out of the recents list, however, and the process is gone. You can
create a test app to further verify, and log the onDestroy() call in
your Activity. It's not called when you back or home out of the app,
or when you launch other apps. It does get called when you swipe the
app out of the recents list though. I do agree that the recent apps
list isn't really "multitasking".
The apps in the list aren't necessarily even running, the processes could have been killed by the
memory manager long before you try to re-open it. However, you can't
argue that the only purpose is to jump quickly to other apps when the
swiping makes the actual process go away.
This is another good answer about what happen when you swipe an app out of the recent apps list. But the part that I liked most was:
Actually, removing an entry in recent tasks will kill any background
processes that exist for the process. It won't directly causes
services to stop, however there is an API for them to find out the
task was removed to decide if they want this to mean they should stop.
This is so that removing say the recent task of an e-mail app won't
cause it to stop checking for e-mail.
If you really want to completely stop an app, you can long press on
recent tasks to go to app info, and hit force stop there. For stop is
a complete kill of the app -- all processes are killed, all services
stopped, all notifications removed, all alarms removed, etc. The app
is not allowed to launch again until explicitly requested.
By Swiping from recent task list removes only from recent tasks ..
It was also called onDestroy before android 5.0 .
Might be you are having issue above api level 20 devices.
System kill normally can not be executed in normal android activity lifecycle.
It just finishes the activity on back press event.
when swiping app to left if any Thread still run in your app Interrupted but service not stopped, when you kill handy app Thread and services are stopped.
the behavior is similar to but not exactly the same as closing an app -- in general (for apps that don't define explicit back button handling) it's the same thing as hitting back enough times from within an application that you exit out of it.check out this link discussion it has some good input on the subject
First, let's get one thing clear: Android MAY NOT CALL onDestroy(). Referring to the Activity Page, from Honeycomb onward, onPause() and onStop() are guaranteed to be called before an app is killed.
Be aware that these semantics will change slightly between applications targeting platforms starting with HONEYCOMB vs. those targeting prior platforms. Starting with Honeycomb, an application is not in the killable state until its onStop() has returned. This impacts when onSaveInstanceState(Bundle) may be called (it may be safely called after onPause() and allows and application to safely wait until onStop() to save persistent state.
So after (hopefully) clearing the air on the Android lifecycle, I think you can achieve what you want by putting the notification removing code in onStop() instead. If you end up needing it back because the user actually DOES come back to the specific Actvitiy(IE not killed), you can bring it back in onRestart().

prevent multiple instances of android app from opening

I've done a fair bit of searching for my issue, but can't find any solutions to my exact problem.
I have an app that has 3 activities in succession. The main activity (on launch), the second activity (where most of the meat and guts live), and then a final activity that is more or less a summary page of what happens in the 2nd activity.
I run into this issue semi-sporadically where if I keep the 2nd activity running in the background (turn the screen of my phone off, or just hit home) and then hit the launcher icon to go back to the app, it creates a new instance instead of returning to my 2nd activity that is running in the background. I can't find any rhyme or reason as to why it happens sometimes and not others (usually it doesn't). Most of the time it takes me right back to my 2nd activity and all is good in the world, but on occasion, it fires up another instance.
Is there anyway to check if an instance is running and ALWAYS return to that instance if there is?
When you hit Home or the screen turns off, the app automatically goes through the onStop() phase. Depending upon the available memory, the app might become a candidate to be killed by the Android OS. There really is no way to prevent the OS from killing an app that is no longer in the foreground - this is an Android OS design. This should most likely not happen if you do not have a lot of applications open.
If the first instance of the app is still around and you launch the app, it will automatically retrieve this instance. Android is designed to never create a second instance of the same app while the first one is still running. Hence there is no way to check is an instance is running. You could use logging inside onDestroy() to see when the app terminates. But again, Android does not always call onDestroy() and might just simply terminate the app.

Resume Back Kivy Application even if minimized (not closed) to recent activity

is there a way to resume back a Kivy application to most recent activity even if minimized? i mean when i am in the application ( a compiled application as .apk) and i want to open wifi for example or check other apps, my application closes and i need to restart it again by pressing on it again...so if i am in the middle of an operation in my application (a calculation or an e-mail composition) and i want to check another application ,all my operation would be cancelled if i do so and of course it is a terrible user experience...
The documentation here describes how to enable pause mode, such that your app will be resumed rather than restarted if you leave then open it again.
The main point is to add an on_pause method to your App class, and have it return True.
Note that you are never guaranteed to be able to unpause again (Android itself may kill paused apps if their memory is needed etc.), so you should also use this method to carry out any state saving you need. However, it's unlikely to be a problem for short task switches, and may rarely or never come up in newer devices with more resources.

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

Categories

Resources