Android: OnDestroy isn't called when I close the app from the recent apps button
Asked Answered
V

3

32

When we press this button

We see the apps which we didn't close, like this

But when we want to close an app from this screen (below image), the method onDestroy() isn't called, however the app is closed. I need to call onDestroy() when the app is closed in this way. How can I do this?

Variegated answered 19/1, 2017 at 14:57 Comment(3)
There are plenty of scenarios in which onDestroy() will not be called. Do not depend upon onDestroy(). If it is called, feel free to use it to clean things up optimistically. But, your app needs to be able to deal with onDestroy() not being called, on any component (Activity or Service).Kane
@Kane so do I have to create a service?Variegated
Clearing the app like this is equivalent to killing a process on a desktop. Your app is just going to die where it's at.Horribly
P
40

As specified in the Android documentation, it is not guaranteed that onDestroy() will be called when exiting your application.

"There are situations where the system will simply kill the activity's hosting process without calling this method"

https://developer.android.com/reference/android/app/Activity.html#onDestroy%28%29

Instead, you can create a service which will be notified when the Task your activities are running inside is destroyed.

Create the service class:

public class ClosingService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);

        // Handle application closing
        fireClosingNotification();

        // Destroy the service
        stopSelf();
    }
}

Declare / register your service in the manifest (within the application tag, but outside any activity tags):

<service android:name=".services.ClosingService"
             android:stopWithTask="false"/>

Specifying stopWithTask="false" will cause the onTaskRemoved() method to be triggered in your service when the task is removed from the Process.

Here you can run your closing application logic, before calling stopSelf() to destroy the Service.

Picaresque answered 19/1, 2017 at 15:7 Comment(7)
I want to send a notification when the app is closed and we didn't press a button in the appVariegated
Using onDestroy() to be notified when your app is closing won't work, as an application is made up of Services, Receivers, background tasks, activities and so on. For example a music playing app with all its activities destroyed might not be closed as it could have a music playing service also running.Picaresque
Furthermore there are this lines of service code in the manifest android:enabled="true" android:exported="true" Are they right?Variegated
Exported means the service will be available to other applications, you want to keep / set this to false. Have enabled set to true so that the service is enabled :)Picaresque
Has anyone noticed battery issues whilst using this approach? I haven't personally, but I'm aware of the performance hit long-running services can have.Picaresque
doesn't seem to fire for me, no errors, just doesn't workKosciusko
+1 Works for me. Starting a service might take up some resource, but in my case I was already using a service. Just had to listen when the called method had to return, indicating Activity termination.Malacca
H
1

You should read some info about Activity lifecycle. There is one thing about onDestroy method, it doesn't get called all time. You mustn't rely on it.

Specify please what are you trying to achive and I'll try to offer better solution.

Suggestion

So, if I understood you right, I can suggest one thing. Start a Service that will fire LocalBroadcast every N seconds (it's not really heavy to system). Register and BroadcastReceiver for this broadcast in Activities. This way you'll get true or false depending on if there is any BroadcastReceiver that can catch your LocalBroadcast. And if no receivers than check for some SharedPreferences value that indicates if Button was pressed.

Humperdinck answered 19/1, 2017 at 15:7 Comment(2)
Service running in the background can be killed by OS anytime once application is destroyed unless it's a foreground service. So what can be a more reliable approach?Preamble
@AlphaGaming the (android) world was quite different back in 2017 :)Humperdinck
T
1

More promising approach than using a bound service would be using activity lifecycle callbacks in the Application. Though the approach shown in the accepted answer would work but the service would be running in the background until the activity is terminated which is expensive. Instead, I would suggest the use of your implementation of Application.

1) Make a class extending Application, then use it by providing its name in the name attribute of Application tag in Manifest file

class MusicPlayerApplication: Application() {
    private val TAG = MusicPlayerApplication::class.java.simpleName

    override fun onCreate() {
        super.onCreate()

        registerActivityLifecycleCallbacks(object: ActivityLifecycleCallbacks {
            override fun onActivityPaused(activity: Activity?) {

            }

            override fun onActivityResumed(activity: Activity?) {
            }

            override fun onActivityStarted(activity: Activity?) {
            }

            override fun onActivityDestroyed(activity: Activity?) {
                Log.d(TAG, "onActivityDestroyed: ")
                val activityName = activity!!.localClassName
            }

            override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {
            }

            override fun onActivityStopped(activity: Activity?) {
            }

            override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
            }
        })
    }
}

AndroidManifest.xml

<application
            android:name=".MusicPlayerApplication"
....

I have tested this approach using logcat, my onDestory is not getting called but onActivityDestroyed in the callback is getting called every time I kill the activity from RAM but this doc says that onActivityDestroyed would be called when onDestory of an activity is called but that doesn't seem to happen. However, I find this approach better than using services.

Tense answered 19/10, 2019 at 13:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.