Callback from framework for out of memory in Android - android

In android,is there any callback that is called when system runs low on memory or out of memory occurs.
For eg: there are three applications A,B,C running.In C out of memory is thrown.How can the application A come to know that so that it can clear its resources ,so that the android system wont kill the application A.

You must extend the Application class, and override onLowMemory() method.
public class App extends Application {
#Override
public void onLowMemory() {
super.onLowMemory();
// handle lowmemory stuff
}
}

Besides onLowMemory() there are other methods.
Use WeakReference to keep your cache and Android will handle OOM gracefully. Also, you can use a Service, which has higher priority than activities and will be destroyed after them.

override onLow memory method and do the stuff that you needed.
#Override
public void onLowMemory() {
// clear the unwanted resources from memory
super.onLowMemory();
}
NOTE: There is no guarantee that this method will be invoked correctly.
This is called when the overall system is running low on memory, and would like actively running process to try to tighten their belt. While the exact point at which this will be called is not defined, generally it will happen around the time all background process have been killed, that is before reaching the point of killing processes hosting service and foreground UI that we would like to avoid killing.
From developer Docs Link

Related

Handle process termination scenrios on low memory

I am searching for best practices for App restarting scenarios on low-end phones, in which during app switching it restarts App with white screen and goes back to last screen where the user was previously. My question is how to save all the essential data in order to overcome such scenarios.
in that case application having onLowMemory() method in Application class
for example :
class MyApplication extends Application {
#Override
public void onLowMemory() {
super.onLowMemory();
// you can save your important data here as it is trigger when your application going to kill as it don't have enough memory
}
}
please let me know if these not working for you.

Handle application states (starting/stopping) not activity states

I'm working on my 1st Android app and wondering how to handle activation/deactivation/starting/stopping globally, not on Activity level.
This great article shows states transition for Activities:
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
Is there something similar for Application states?
For example at iOS and Windows Phone app there is clear app states separated from activities (views, controllers, whatever).
I'm asking because I want to perform certain operations only once per app loading/exiting not with every activity starting/stopping
The answer is There is Simply No Direct method to do this
rather than in Application Class you can catch these events
#Override
public void onLowMemory()
{
super.onLowMemory();
}
#Override
public void onTerminate()
{
super.onTerminate();
}
So you will have to handle it in all the Activities you will be having
the following methods
onResume()
onStart()
onRestart()
onPause()
onDestroy()
You will have to implement in all Activity to handle for all application
A suggesstion
You can have some Variable in Application class to save application state
say create a variable like
public static boolean isPaused;
and set it from all activity on state change
The question you're asking is applicable for iOS and Windows but not really for Android.
Android doesn't really have a concept of an application as an object, although there's an Application class. Instead, an app is a loose collection of Activities. There are many good reasons for this state of affairs; for example, it supports fast app switching and easy interaction between Activities of different apps.
The best way to coordinate your "app" so that one Activity doesn't try to do something that's already been done is to use SharedPreferences to store app state. Nearly every other way of doing it is less preferred. Even if the system kills off your entire app, SharedPreferences will maintain the current state. The Application object won't.
Also, Android is based on pausing and resuming. An Activity or activities are created, pause, and resume. They may be destroyed, but that's an extreme case. A corollary to this is that apps should not have an exit button; there's no need for one. I sometimes see apps that have one, but what they're really trying to do is shut down a background Service or process. The best way to do that is to have an affordance that says "Sleep" or similar.
Have all activities inherit from the same hierarchy and put whatever you want in OnCreate, OnPause, OnResume, OnStop, OnDestroy and call the super where applicable.
Example
Parent
IamTheParentActivity : Activity
protected void onCreate()
{
setApplicationState(ApplicationState.Running);
}
protected void onPause()
{
setApplicationState(ApplicationState.Paused);
}
private void setApplicationState(Enum ApplicationState)
{
//Some Application Level Variable
Application.State = ApplicationState
}
Children
IamTheChild : IamTheParentActivity
protected void override onCreate()
{
base.OnCreate;
do other stuff
}

Use of onDestroy( ) in Android

If Java provides Garbage Collection, then what is the need of onDestroy() in Activity Lifecycle?
onDestroy: The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it), or because the system is temporarily destroying this instance of the activity to save space.
Here is an example......
public void onDestroy() {
super.onDestroy();
}
OS decides when things "go away." The onDestroy is there to let your app have a final chance to clean things up before the activity does get destroyed but it does not mean that the activity will, in fact, be GCed. Here is a good article that I recommend people to read that relates to creating an exit button. While it's not exactly what you asked about, the concepts will help you understand what's going on.
You can use onDestroy() to finalise the program. I have used it in the code bellow to tell the server that the client is closing its socket to the server so I can notify the user on the server end that the client has disconnected.
client:
...
protected void onDestroy(){
super.onDestroy();
if(connected) {
clientMessage.println("exit");
clientMessage.close();
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
finish();
}
...
server:
...
while (connected) {
input = clientMessage.readLine();
if ("exit".equals(input)){
break;
}
...
}
...
onDestroy() is a method called by the framework when your activity is closing down. It is called to allow your activity to do any shut-down operations it may wish to do. The method doesn't really have anything to do with garbage collection (although your shut-down operations—if any—might involve releasing additional resources that can be gc'ed). In particular, it has nothing to do with C++ destuctors (despite its name).
If you have no shut-down operations to do, you don't need to override it. The base class does essentially nothing.
onDestroy may be called when an activity is destroyed, but you can not count on it. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.
See: http://developer.android.com/reference/android/app/Activity.html#onDestroy()
In the Android Activity Lifecycle's onDestroy docs:
onDestroy() is called before the activity is destroyed. The system
invokes this callback either because:
the activity is finishing (due to the user completely dismissing the activity or due to finish() being called on the activity), or the
system is temporarily destroying the activity due to a configuration change (such as device rotation or multi-window mode)
The Activity#onDestroy() API docs also answers it quite well:
This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. source
As the quote from the docs say, its for preventing a destroyed activity leaving things around (e.g. memory leaks through referencing, threads), but only when the rest of the app still runs. If the application process ends, it doesn't matter if you forget to clean up threads or other resources since the OS will do it for you. You don't need to override onDestroy.
There is no need to do what sam786 is doing (overriding and just calling the super method) as that is absolutely useless. All other answers seem to go along the lines of "clean up", but don't explain what kind of clean-up or when. You should not be saving any data in onDestroy(), as you can't guarantee it will be called, so you will lose data sometimes. It won't be called when you press the home button, for example (the case where you want data to be saved).
The onDestroy is there to let your app have a final chance to clean things up before the activity does get destroyed
Article Exit Button in Android
It gives your program a chance to do things like cleanup resources (say threads) so that they don't pollute the associated application. If you don't have any use for it, then don't override it.
See:onDestroy()-Android Reference

onDestroy, killing a running thread

I have a method like this in my class which extends Activity
#Override
public void onDestroy() {
Log.i("onDestory: ", "Inside OnDestory!");
bluetoothCommunicator.destroyedApp();
super.onDestroy();
}
The method destroyedApp() look like this:
public void destroyedApp() {
if(server != null)
server.destroy();
}
Where server is an Instance of a class which extends Thread
Here is the scenario:
I'm opening the application for the first time, inside my onCreate method, I create a new instance of the bluetooth class which sets up the BluetoothServerSocket, this works fine and I'm able to transfer files to my phone.
This also works when I have my application in the background, because the thread is still alive.
But
When I'm killing the application, according to the Activity Life Cycle
The onDestroy() method should be called by the Android Framework. And when I'm launching the application once more, the onCreate method should be called, but it doesnt seems that an instance of the BluetoothServerSocket is being created. I have no LogCat info, because the device which sends the bluetooth file, only says:
Error Log:
Write Error:
Transport endpoint is not connected
__obex_connect:
error=-2
Unable to connect to the server
Error
Which tells me that the BluetoothServerSocket is not "alive"
Any suggestion on how I can accomplish this?
There is generally no guarantee that the onDestroy() method will be called at all. According to the docs:
Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.
Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.
So I would first test if it is being called reliably.
Also, you are callling super.onStop() in your onDestroy(). It should be super.onDestroy()
Since I cannot comment, I am posting here.
As, commented by Egor I dont think you can call onStop() from within onDestroy(), Android will itself call onStop() following onPause() depending on the memory.
Now, note that stop(), suspend() and destroy() methods of thread are deprecated, the only safe way of terminating a thread is to have thread exit its run().
Now, when you are calling server.destroy(), there is a possibility that it still holds some link in the memory and therefore Garbage collector will not be able to garbage collect your activity. Hence, I believe this could be the possible reason why your onDestroy is not called.
Point me if I am worng.
How are you killing your application? I was looking for a solution for your problem in the Application class and I came across this information about the onTerminate() method:
This method is for use in emulated process environments. It will never be called on a production Android device, where processes are removed by simply killing them; no user code (including this callback) is executed when doing so.
I remember I had a similar problem in one of my apps, where some components' onDestroy() method was not called because I used the "Clear memory" button in the Task Manager (Samsung Galaxy 2)

Detect whether application is quit by the OS because of low RAM

In the application I'm building, I need to detect the application quitting if and only if the application has been quit when its in the background because the OS is reclaiming memory.
From my own experimentation, the onDestroy is called on EVERY instance. I've tried checking for isFinishing but I'm not 100% sure which situations this isolates it to.
#Override
public void onDestroy()
{
super.onDestroy();
Log.i("V LIFECYCLE", "onDestroy");
if (!isFinishing())
{
// are we here because the OS shut it down because of low memory?
ApplicationPreferences pref = new ApplicationPreferences(this);
// set persistant flag so we know next time that the user
// initiated the kill either by a direct kill or device restart.
pref.setThePersistantFlag(true);
Log.i("DEBUG", "onDestroy - ensuring that the next launch will result in a log out..");
}
}
Can anyone shed light on my issue here? Thankyou.
Through trial and error I have worked out a solution that works perfectly for anyone thats interested. I have narrowed down the case when the application state is being resumed (onResume) in the case of the OS reclaiming memory.
public boolean wasJustCollectedByTheOS = false;
#Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
super.onSaveInstanceState(savedInstanceState);
// this flag will only be present as long as the task isn't physically killed
// and/or the phone is not restarted.
savedInstanceState.putLong("semiPersistantFlag", 2L);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
long semiPersistantFlag = savedInstanceState.getLong("semiPersistantFlag");
if (semiPersistantFlag == 2L)
{
savedInstanceState.putLong("semiPersistantFlag", 0L);
this.wasJustCollectedByTheOS = true;
}
}
// this gets called immediately after onRestoreInstanceState
#Override
public void onResume() {
if (this.wasJustCollectedByTheOS){
this.wasJustCollectedByTheOS = false;
// here is the case when the resume is after an OS memory collection
}
}
I don't know whether its help you or not,
From Android Activity class,
public void onLowMemory ()
This is called when the overall system is running low on memory, and would like actively running process to try to tighten their belt. While the exact point at which this will be called is not defined, generally it will happen around the time all background process have been killed, that is before reaching the point of killing processes hosting service and foreground UI that we would like to avoid killing.
Applications that want to be nice can implement this method to release any caches or other unnecessary resources they may be holding on to. The system will perform a gc for you after returning from this method.
And Since: API Level 14
public abstract void onTrimMemory (int level)
Called when the operating system has determined that it is a good time for a process to trim unneeded memory from its process. This will happen for example when it goes in the background and there is not enough memory to keep as many background processes running as desired. You should never compare to exact values of the level, since new intermediate values may be added -- you will typically want to compare if the value is greater or equal to a level you are interested in.

Categories

Resources