I have an application that I suspect might be leaking a thread or its context. What makes me think so is that after closing the app, the process is still running (visible process monitoring applications). I've cut everything in the code, going as far as calling finish() from the onCreate. The process is still around and annoying me.
I've read that (from here)
An empty process is one that doesn't hold any active application components. The only reason to keep such a process around is as a cache to improve startup time the next time a component needs to run in it. The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.
How do I know if my process is still around because of circular reference or context leak or anything else equally bad or if is simply that the process is empty?
The fact that you still see the process will not give you any information about the existence or not of references to objects in your application. There's no magic that's going to answer that for you.
If you are worried, you should inspect where (if anywhere) you are registering callbacks (AKA listeners) with system services. This is a common root cause. the correct pattern is to register in onResume() and unregister in onPause(). You are guaranteed those will be called when your app pauses / resumes.
Unless you have a really special purpose reason, don't as suggested above use the various methods for manually killing your process. The OS has memory management built into it. Don't try to be smarter than the OS. Android keeps application artifacts (activities, services, etc) in memory even when they are "finished". This allows them to re-start faster the next time. If it needs the memory for something else, it will remove the unused processes from memory.
How are you closing the application? Hitting the back button or the home button doesn't close the application, it just finishes (or pauses) the activity. You have absolutely no control over when Android decides to terminate the process and kill the application.
finish() doesn't actually kill your application. In almost every case it's the exact same as if the user had hit the back button.
ActivityManager.killBackgroundProcesses(yourPackageName) may be what you're looking for.
Related
I'm new to Android development. I'v developed an android application which needs to store the connection/data even after 1 hour. Currently I have all the data and the connections(chromecast mediaplayer) in a singleton class. But, when the user puts the app into the background for about an hour, the activity is destroyed so the connections,data etc are lost causing my app to crash when re-launched.
I've read up on the android services, Can I use these services to hold the singletons so even when the activities are destroyed I can have data binded back to the views when re-launched?
Or is there a way to make sure that the activities are not destroyed when android decides to do a cleanup?
Please advise
Thanks.
I think you might misunderstand what an Android application is.
Your application is a bunch of components that run in a single Linux process. Components come and go, within that process. You have absolutely no control over the lifecycle of the process itself.
The answer to part of your question is that "yes" a Service will stick around after an invisible activity is destroyed.
When an Activity becomes invisible, it gets destroyed. If your process is not doing anything else, then the process is likely to be killed too.
If your process is also running a Service, it is less likely that it will be killed. It is just less likely, though. The process will eventually get killed. When it does, your singletons will be gone. There is nothing you can do to prevent that. So the answer to the second part of your question is "no". You cannot depend on singletons in your service to be around when the process is relaunched
You might look into using the Application object. Its lifecycle is roughly the same as that of your process. It will not live forever but it will be around whenever any other component of your application is around (except ContentProviders).
It sounds like you want to keep connectivity to a chromecast device around when your application is in the background. Obviously services can be helpful but I have a few comments that may come handy:
Services can be killed by system but based on how you have set them up (e.g. the return value of onStartCommand()), they can be restarted by the system. When that happens, you cannot expect that your dynamic data is still there (for example your singleton). You need to include logic to recreate what you need again (for example, rebuild your singleton)
Phone can go to sleep when left for a little while (or user can lock his/her phone), so when phone goes to sleep, wifi may drop after a little while, based on the phone settings and the build on your phone; some do this more aggressively and some not (even if you hold a lock, it can still happen). The point is that you have to assume that it may happen. Even if you have a service, your Cast connection will go down due to wifi loss, so the proper way to handle things is not to try to keep the connection up all the time (since you can't) but is to have logic to re-establish connection when circumstances is right. In order to do that, you need to preserve enough information to be able to bring things to the state that they were. Your logic should also be intelligent enough not to reconnect if it shouldn't.
Android O.S can destroy any activity , when it is low at resources it destroys any activities to make more space for other apps.
But you can use background service to hold your singleton
You can use this link to create your background service
I have a simple app with native code. That is, an Activity plus native code.
When the activity is entering background, I keep the native code running to do some processing. The problem is when the activity is killed by OS (due to low resource), JNI code seems to have no knowledge of what happened in Java land and still doing its job, hence wasting resource. Why does Android kill just the Activity instead of the whole process? and in this case, how does native code know that the activity was killed? OnDestroy() may not get called.
An Activity in an Android application is described in the documentation as
An activity is a single, focused thing that the user can do.
It is usually something that is visible on screen and has the user's attention. It has associated with it a state-machine that describes the life-cycle of being shown and hidden when another activity become active. The operating system is at liberty to start and stop activities as it choses - and memory permits.
In addition, a key point of the Android architecture is that activities and services are reusable software components and do not necessarily have a one-one relationship to processes. Inside the same process as your activity may be a service in use by another process in the system.
If the JNI portion of your code is still active in the background when an activity has received an onPause(), onStop(), onDestroy() notifications, it can only be because you haven't forwarded these messages to it. The system certainly doesn't know how to clean up native code's resource utilisation - particularly memory allocated with new() or malloc(). Unless you free it, it will only ever be recovered upon process termination.
If your concern is that your activity is not being killed fast enough by the system and as a result holding references to resources in native-land, it's a good sign that the system isn't resource limited.
You might consider implementing the native portion of your application as a Service and have it self-destruct after short periods on dis-iuse.
You could have multiple Activities in one Android Application. As your Activities go into the background, they can be killed to reclaim resources. The application is typically kept around until the phone runs really low on memory, or the user goes and kills your app manually. The process sticks around until the application is killed, roughly speaking.
Because you can continue processing in the background, when your Activity is re-created you can check the status of your global variables and perhaps pick up where you left off.
Keep in mind that Activities are killed quite often, so there's not much point to doing processing in the background but stopping when the Activity is killed. You might as well stop when onStop() is called in this case.
There has been instances where we need some code must be executed at the end no matter what happens to the application. Is there any way we can achieve the finally() functionality in Android?
Note: OnDestroy will not be called during the crash.
For the matter of fact even finally() is not a full proof method when the JVM exits. But in Java we do not see too many JVM exits. But in android since we have a DVM for every app process, we need a way to execute the final code else, we end up leaking the memory and battery consumption shoots up.
You can't leak memory when the application/vm crashes or is killed. In that case, the process is gone and any memory associated with it is gone.
If you are talking about allocating and freeing memory that's in a different process, you can get a Binder from the consumer process, and then use the Binder.linkToDeath functionality to receive a notification when that process dies.
Your best bet would be to run the cleanup operations in the onPause() of every Activity individually.
There is nothing like finally() in Android, as when an app crashes the entire process is simple terminated. Even normal methods like onPause() aren't called. Everything included in the process (Activities, Services, Receivers, Threads etc) is completely killed.
I am not sure what you mean by a leak here when your original process is anyhow not running.
Still one thing we did to handle such scenarios is to have a 'watchdog' process, though we had to do this in native code running in Android.
In your case, you could potentially create a service and make it run as a sperate process by specifying the
android:process=":remote"
flag in your manifest file. Now that service can potential watch for the main application process and do some cleanup if possible. Ofcourse you would need a way for the service process to know about which elements to clean up.
Hope this helps.
There are various ways to die:
Killed by system. Shouldn't happen while you're in the foreground, so make sure you close stuff as part of the Android lifecycle.
Fatal exception. You can deal with this by using a global uncaught exception handler. See Ideal way to set global uncaught exception Handler in Android
Native crash. Not much you can do about this. In some cases you can try to recover with a signal handler, but the app will be in a very uncertain state, so it's generally a bad idea and unlikely to work.
Looking through some of the other comments, it sounds like your device has a bug in the Camera driver that is causing it to be held open even after the process that opened the camera has died. This is a system bug -- the app shouldn't have to manage system resources when it crashes. (But, until it gets fixed, you've got to work with what you're got.)
I am trying to determine how to keep my app safe under various Android lifecycle conditions, such as another app being start, phone going to sleep, etc. I understand the lifecycle states and the event methods I can hook into, but I am not sure how memory is handled in regard to things I already had references to. I am well aware that my app may be killed at any time if the OS needs to, but what about individual references? Here are a few example scenarios: if my app is running and the user gets a phone call, or the user starts another app, or the phone goes to sleep. Assuming my app did not get killed, can I safely use my references or will I get random null pointers? I guess what this comes down to is... does Android either kill or not kill and app or will it reclaim some memory (where there are still valid references) from an app without killing it?
Most of the time when the user switches to another app or answers the phone, you app will simply be suspended. When it comes back, onResume() will be called and it will continue on it's way with no issues. References and that kind of thing should be fine. It is recommended that you unregister listeners and re-register them in onResume(), though.
You should always remeber that your app may also be completely killed at any time, so save your data.
The truth is most of the time the application will not get killed in a brief interruption, for example a call or email, but if you want support these situations you should preform cleanup or saving the data in onPause(). When the application comes back it will execute onResume().
References will not disappear until the activity is destroyed, do not worry about NPE in the pause -> resume scenario unless you are doing something very odd.
If you are using listeners or GPS, you should unregister during onPause() and resume it later.
Is there something in the Android developer guidelines that disuades developers from providing the option to "exit" (stop running) an application from within the application itself?
I love multitasking and all but it's not clear to me why:
the vast majority of apps don't have their own Exit functions and hence just keep running forever
don't give you a choice about running when you turn on the phone - they just do by default
Both of these things lead to memory usage constantly increasing and your device running with this performance burden all of the time despite the fact that you may only want certain apps to run some of the time.
Am I missing something?
Is there something in the Android
developer guidelines that disuadea
developers from providing the option
to "exit" (stop running) an
application from within the
application itself?
Yes. It is generally not needed, just as it is generally not needed to restart a Web server because some user with a browser decided (s)he is done with a Web app.
the vast majority of apps don't have
their own Exit functions and hence
just keep running forever
They don't keep running forever. Android will close things up as needed.
don't give you a choice about running
when you turn on the phone - they just
do by default
Those developers aren't paying attention to me.
Both of these things lead to memory
usage constantly increasing
Generally, it doesn't. If you find specific apps that do this, uninstall them.
and your device running with this
performance burden all of the time
Generally, it doesn't. If you find specific apps that do this, uninstall them.
Also, this question is a duplicate of this one.
"Both of these things lead to memory usage constantly increasing"
Which doesn't matter since Android apps are limited to a fixed amount of RAM. Freeing RAM won't give more RAM to other apps.
Essentially, there's no need for a quit button as long as the developer does a good job of designing their app. Android activities are stopped when they aren't visible and resources are needed elsewhere, so the are no longer consuming resources. You can read about the lifecycle here:
Here's a related question:
From Google's Android Application Fundamentals page:
Shutting down components
A content provider is active only while it's responding to a request from a ContentResolver. And a broadcast receiver is active only while it's responding to a broadcast message. So there's no need to explicitly shut down these components.
Activities, on the other hand, provide the user interface. They're in a long-running conversation with the user and may remain active, even when idle, as long as the conversation continues. Similarly, services may also remain running for a long time. So Android has methods to shut down activities and services in an orderly way:
An activity can be shut down by calling its finish() method. One activity can shut down another activity (one it started with startActivityForResult()) by calling finishActivity().
A service can be stopped by calling its stopSelf() method, or by calling Context.stopService().
Components might also be shut down by the system when they are no longer being used or when Android must reclaim memory for more active components. A later section, Component Lifecycles, discusses this possibility and its ramifications in more detail.
So it seems like Content Providers and Broadcast receivers should never be explicitly shut down, as they are inert while not handling their specific events.
As for Activities, I would argue in favor of having an end to it, but in certain cases. If your app has a finite state in which the user is done using it, why keep it alive until GC gets it? The activity manager still needs to keep track of that Activity while the user has finished their task. My best example for this is the Calculator. You open it, you have it solve a problem for you, and then you close it. If the onCreate function is so expensive that it's more effective to do onCreate once and then onRestart whenever the user moseys back to your application then you're probably doing something wrong. Maybe I'm misinterpreting how Android handles Activities, and if so I'm always interested in learning more :)
It all comes back to the answer that users want total control of their running and auto-start list and what they do and don't want installed, example: google maps, etc etc. there are no two ways about this.