As reference, this is on Android, and this is the Titanium Forum Post
I'm noticing this issue with several applications I've done with Appcelerator, all of them: no matter if they are simple apps or complex apps, but is more frequent in larger apps.
For example, I'm working on an application that needs to notify its location (GPS location) every 5 minutes. The application works perfectly when working in foreground, however, every time I put the app on the background (if I minimize the app by using the Home button) the application just crashes and all the services are stopped.
For notifying the application, here's the flow I'm using:
When I start the application, I start an Alarm, using the AlarmManager module.
This AlarmManager, adds a new Alarm Service, which will be triggered every 5 minutes.
Every 5 minutes, the AlarmManager starts the service and notifies the server with the current location.
This works great.
If I hit the "Home" button, the application just crashes (on the Application Manager) sometimes, but is more frequent when using other applications on the foreground while leaving this app on the background.
I thought this was because the main Activity was stopped, so I decided to maintain the main activity / task state by using android:alwaysRetainTaskState="true"
If I reopen the application, the application just restarts. This happens more on low-end devices than on high-end devices, which makes me think that this is a memory issue.
I have some questions:
Is this the expected behaviour?
If so, how can I mitigate this (maybe a native module/service?)?
Is my current flow the best flow for doing this or is there a better approach?
Any thoughts are more than appreciated.
For answering my own question: After a lot of tests, we saw that the problem was more frequent on older devices.
By reviewing the components, elements and doing an extense memory research, we discovered that this actually has to do on how Android manages Applications and the memory.
If OS decides your application is consuming too much memory on the background, it's able to remove it by any time. No matter if it's executing an Alarm or not.
With devices with more memory (newer devices), the problem just disappears.
Related
On Windows, MacOS and Linux, when an app is closed, the norm is that its process is also killed. This happens as default on Windows/ Linux, and on MacOS, it still seems like a good idea to press CMD+Q to kill the process when no app window is open.
On Android (and iOS too) when the app is backgrounded, its process still keeps living in the memory till the OS finds it necessary to push it out. The process can be killed but this step is not the default OS behaviour and is somewhat discouraged by the UX.
Why?
Update
Some of the replies do seem to suggest that there are potential benefits in keeping the app in memory. So a further follow up will be, why then main stream desktop OS(es) do not follow the same approach to reap all the same benefits?
Android is very good at managing its resources. It has a certain amount of memory (RAM) to work with, and it’ll happily allow apps to use as much as they need for best performance.
If RAM starts to get a bit short, and other apps and tasks need some, then the OS will quietly close one of the apps running in the background that you haven’t used for a while, and assign that app’s RAM to the new task.
As a result, apps can stay in memory for hours, days or potentially even weeks since you last used them. And this is fine. They’re not draining the battery or using other resources so there’s no downside; the upside is they will load much quicker when you need them, and load them right back to the place where you left off too.
(It’s also worth noting at this point that there’s really no benefit in keeping RAM free. RAM exists to be used, and using all of it at any given time—or virtually all of it at least—will ensure your phone or tablet runs smoother than if you try and keep some RAM free.)
With all this in mind, it becomes clear why closing apps can have a worse effect on Android than leaving them open.
Ref: androidtipsandhacks.com
Answering to your question update and agreeing with the already posted answers stating that keeping an app in memory may be better for battery and app resume/start up.
A mobile device is designed to be fully mobile, to be in your pocket or hand all the time, and connected to an electricity outlet just for charging, and usually nothing more. So, it must have a battery saving centric design.
A desktop is always connected to an outlet, so doesn't have the battery shortcomings and requirements of mobile devices.
About laptops, although they are portable, they are actually used most of the time also connected to an electricity outlet. The fact that they can be carried from one point to another doesn't make them comparable to mobile devices.
So, although desktop OS(s) now days have battery saving features tailored mostly for laptops, their design is focused with the fact that the host device will usually work connected to an electricity outlet, and they have never evolved to have a battery saving centric design, which is a "must have" requirement for mobile devices.
On the other hand, if you want to consider not the battery but the app resume/start up benefits, then actually such feature is already implemented in both types of OS(s), but in a very different way. For example in Windows you can minimize a program, this is the exact same thing as pressing the home button in Android. To close it you press the x button a the corner or the program's exit option, that would be like going to Android apps task manager (recent apps history) and killing the app.
Because some applications behavior relies on background services that can not work if the main process is killed. When you swipe off an application from the recents, you're not really killing the app, the background services are still there.
Imagine that you close Whatsapp and the OS thinks that it's a good idea to kill the entire process. You wouldn't recieve any message unless you re-launch the app.
According to documentation, there are 4 states of application process in android app.
Let's look at a few cases.
1. App has running Activity. User presses home button.
In this case app status will be moved from Foreground to Cached.
Cached state is used for providing better UX, when user switches between apps. Because opening a cached activity is much faster then restoring it from saved state.
2. App has running Activity and Service. User presses home button.
In this case app status will be moved from Foreground to Service.
Service state is used for processes which have some unimportant background job. In this case process is kept, because it has some background job to do. Of course you can move your Service to a separate process, but it is not a default behavior.
3. App has running Activity and foreground Service. User presses home button.
In this case app status will be moved from Foreground to Visible.
Visible state is used for processes, which are visible to user, but he doesn't interact with it directly. Foreground Service is used for doing important background job and keeps process at Visible state. Again UI and Background parts of app by default are placed in same process.
Android app that I am working on reads from near by beacons(devices) using bluetooth. It works fine when the app is in the foreground (tested it for 20 minutes). However, few minutes after app goes to background it stops reading.
I notice when app goes to background, onpause() method is executed; still my app reads for few minutes and then simply stops reading anything (when I manually bring the app to foreground, oncreate method is executed and app continuous normally).
Why is my app stopped reading few minutes after it went to background. My app is an activity and not service.
should convert the activity to service or
should I create intentservice or
should I create foregroundserive
I donot understand the difference between above 3 types of services and if any of them would help me.
Though slightly older threads, I reviewed Prevent that the app get stopped or paused by the OS and How can we prevent a Service from being killed by OS? and my app killed by android system when it running in background
But I am lost. Any discussion is appreciated
EDIT
As I understand from #davidgyoung answer, I have to write a service. I assume GUI portion of my app goes into mainactivity; then how I can ensure my mainactivity/GUI is still active in memory and was not killed by Android by the time service tries to broadcast/notify GUI
/EDIT
An Activity is not designed to run for long periods in the background. The Android OS will destroy activities that are not visible as memory is needed for other functions. While a Service is the proper alternative, even a service will be destroyed under memory pressure by the OS, so you still need to restart the service if it is killed by the OS and you continue to want to do beacon scanning.
All of these issues came up when we built the Android Beacon Library, and we settled on these solutions to keep scanning going:
Use a Service to scan for beacons in the background. It does not have to be an IntentService, but that is a reasonable option.
Use an AlarmManager to restart the scanning service 5 minutes in the future in case it gets killed. (This delay allows the OS to time to recover from a temporary need for extra memory.) If the scanning service is still running, just reschedule the alarm.
Register for OS level events (boot, power connect/disconnect) to restart the scanning service at a later time if the user kills the app with the task switcher.
All of this is built for you if you decide to use the Android Beacon Library (and we welcome contributions, too!) If you want to roll your own, you may want to look at the source code to see how these things were built. Feel free to copy and modify, too. That's the beauty of open source!
Full disclosure: I am the lead developer on the Android Beacon Library open source project.
I am using AlarmManager for repeated background process. My app repeatedly requests data from server in 5 sec interval. But after some long time, when I open my app it crashes. I can't figure out why.
How should I execute a background process repeatedly? Should I use AlarmManager,Timer` or something else?
My background process should run always even when the app does not have focus or isn't active.
My app repeatedly request server for data 5 sec interval.
Users with mobile devices, like phones and tablets, will not appreciate your behavior. They will not appreciate your consumption of battery life and your consumption of bandwidth. Device manufacturers and Google are continuing to take aggressive steps to prevent applications like yours from behaving this way, both automatically and by giving users the tools to find ill-behaving apps like yours and get rid of them.
But After some long time when i open my app its crash
Most likely, you have a bug in your app. You will need to fix the bug. Since you have provided no details of your crash, such as source code and a stack trace, nobody can really help you with that.
Which is the best for repeated background process, AlarmManager, Timer or something else?
Switch to a user-configurable and less-crazy polling period (e.g., every 15 minutes by default), then use AlarmManager in conjunction with an IntentService, so that your process can cleanly go away
Or, switch to having the server send messages to the device when the data of interest changes, such as via Google Cloud Messaging. This will allow you to drop the polling period to something infrequent (e.g., every hour by default), as a fallback mechanism in case you miss a push message for some reason.
My background process should run always though the app is not on focus or active
Your users will disagree with you. They do not want apps running all of the time, tying up system RAM. They really do not want apps that consume battery and bandwidth the way that you are proposing. The users will get rid of your background process, either by:
swiping your app off the recent-tasks list
using a third-party task manager
force-stopping your app via its entry in the application list in Settings
uninstalling your app
Ok, so I'm developing an Android App with news. When user runs App for the first time, a separate thread runs, then a infinite while( true ) loop starts, inside a loop a connector downloads text from the Internet to the notification and sends this notification, then sleeps for 8 hours. Which way is better to make it working best, a thread with way as above or alarm manager? Or, maybe there is a different and better way?
For now I've done two ways for testing, both work good, but I have no idea how to check which one is more efficient, which won't be killed by android, which eats less resources, etc.
And second question, is there any way to restore the loop when someone kill app? I was testing with Advanced Task Killer Free and an app Flashy (Flash Player Loader). I killed the Flashy, but 5 seconds later app was running again, so it propably is possible, but how?
And for those who think I'm developing annoying ad - no, App which I'm developing just reads news from the Internet.
Hope somebody helps,
Thanks in advance.
Thread vs AlarmManager
AlarmManager
As per Android doc
The Alarm Manager is intended for cases where you want to have your
application code run at a specific time, even if your application is
not currently running.
So the advantage you get here is you can perform specific task in future even if you application is not in running state.( Here you can proudly call yourself good android citizen since you are not residing in android memory to get your task done).You just tell android I want to get this task executed at particular time,Android will automatically start your application at that particular time even If it is not running.
If you want to acheive same thing with thread then your thread should be alive till the time task does not start executing.( The disadvantage will be android will not kill the thread till the time process is alive and your tread will unnecessary eat up memory).
Hope this will clear your doubt.
In your case I would definitely use the alarm manager.
As a general rule of thumb, if your application "sleeps" and routinely checks for new content in long intervals (8 hours is a long time), you should use the alarm manager.
This way your app doesn't need to run in the background, thus battery life is conserved, and the application's functionality will not be affected by Android killing the service in cases of low memory.
Regarding your second question - if the Android system kills a service due to low memory, it will restart it as soon as possible. However if you kill the service manually then it should not be restarted, even if it is possible through some hack.
I want to perform action/event when application killed from task manager or any other app. Is there any to perform action when application killed. My application is running in background like service. If i terminate the application then main service stop . I want to start it again.
No, there's no reliable way to know if your application was killed by a another process. The whole point of "killing" an app is to terminate it as soon as possible, without letting it run any code.
== Do not actually use the following suggestions in production application. They are here purely as potential technical solutions, but in general are not a good idea for apps running on end user devices. ==
It might be possible to use IBinder.linkToDeath() from a secondary application, which acts as a monitor for your primary one. However, you will have to convince the user to install the secondary app as well. If you can do it, you could establish two-side monitoring between the two apps, and have one of them restart the other if the second is killed.
You could also attempt to set an alarm through the AlarmManager that fires every so often, to restart your application if it happens to be killed. However, if your alarm period is too big, you risk having certain period of time where your app is not running. And if your time period is too small, most likely your app will not be allowed by Google in the Google Play Store, and the malware app analysis on the phone (JB+) might kick in. Also, alarms that kick in too often will keep the device awaken, and drain the battery very fast.
If you kill some process, you just kill it, so it stops working immediately. There is no event sent to the application.
I looked for the same thing and the answer that i found is : NO, the application does not go to OnDestroy() or anything like that.