97

I need to know when the user kills my app (Force stop). I've been reading the android lifecycle, which has the onStop() and onDestroy() functions, these are related to each activity the user ends on my app, but not when the user forces stop or kills my app.

Is there any way to know when the user kills the app?

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Darknoe
  • 1,190
  • 1
  • 9
  • 11
  • 1
    It's simply not possible. See http://stackoverflow.com/questions/16013578/how-to-detect-if-android-app-is-force-stopped-or-uninstalled – transporter_room_3 Jan 10 '14 at 09:23
  • Why do you need to know when they kill the app? If your app is coded well, you really wouldn't care if they killed it. – npace Jan 10 '14 at 09:30
  • 2
    Project specifications need to know when a user kills this app. I don't like this approach, but i have to code what they ask me to. – Darknoe Jan 10 '14 at 09:34

9 Answers9

153

I have found one way to do this.....

  1. Make one service like this

    public class OnClearFromRecentService extends Service {
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.d("ClearFromRecentService", "Service Started");
            return START_NOT_STICKY;
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d("ClearFromRecentService", "Service Destroyed");
        }
    
        @Override
        public void onTaskRemoved(Intent rootIntent) {
            Log.e("ClearFromRecentService", "END");
            //Code here
            stopSelf();
        }
    }
    
  2. Register this service in Manifest.xml like this

    <service android:name="com.example.OnClearFromRecentService" android:stopWithTask="false" />
    
  3. Then start this service on your splash activity

    startService(new Intent(getBaseContext(), OnClearFromRecentService.class));
    

And now whenever you will clear your app from android recent Then this method onTaskRemoved() will execute.

NOTE: In Android O+ this solution only works when the app is full-time in foreground. After more than 1 minute with the app in background, the OnClearFromRecentService (and all other Services running) will be automatically force-killed by the system so the onTaskRemoved() will not be executed.

user3429953
  • 352
  • 3
  • 19
Faisal Khan
  • 2,574
  • 3
  • 20
  • 36
  • Clicking "Force Stop" explicitly doesn't trigger onDestroy for all devices. – stdout Dec 22 '16 at 09:53
  • On API 26, most of the background services are killed by system even though the app is still on recent apps and clicking recent apps try to continue savedInstanceState. – fthdgn Mar 26 '18 at 21:45
  • @AlonMinski It's because those manufacturers add custom apps for battery saving that kill your background services once you clear your app from the recents list. You have to manually protect your app against this system. Or else, your services will only be restarted when user opens the app again – joao2fast4u Apr 11 '18 at 13:55
  • I have a object reference that should be saved while user killing app. I used onTaskRemoved method, this method is calling as expected, but the object reference is cleared(null). Is there any other callback there i can save the reference before it is cleared. – Anbarasu Chinna Jan 17 '19 at 14:11
  • @AnbarasuChinna Objects in Android shares the same memory with the app so once the app is killed it means everything is cleared. But you can do one thing here, convert the object into JSON and pass into the service. I hope this will work for you. – Faisal Khan Jan 17 '19 at 21:29
  • 1
    @FaisalKhan I've pretty much implemented your solution verbatim. while `onStatCommand()` is called, `onDestroy()` and `onTaskRemoved()` never get called. any thoughts on what i might be doing wrong? – El Sushiboi Feb 20 '20 at 17:53
  • No this will not work on API > 26 with the new restriction of google on background services. – Faisal Khan May 29 '21 at 19:48
30

there's no way to determine when a process is killed. From How to detect if android app is force stopped or uninstalled?

When a user or the system force stops your application, the entire process is simply killed. There is no callback made to inform you that this has happened.

When the user uninstalls the app, at first the process is killed, then your apk file and data directory are deleted, along with the records in Package Manager that tell other apps which intent filters you've registered for.

Community
  • 1
  • 1
Taranfx
  • 10,361
  • 17
  • 77
  • 95
5

Create a Application class

onCreate()
Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.
onLowMemory()
This is called when the overall system is running low on memory, and actively running processes should trim their memory usage.
onTerminate()
This method is for use in emulated process environments.

Even if you are application Killed or force stop, again Android will start your Application class

rajahsekar
  • 916
  • 1
  • 11
  • 25
2

for some cases, you can create splash screen page to determine if app has been killed previously by system.

it basically a screen with intent filter main/launcher, and will be finished, and changed to main activity.

so, every time user visit splashScreen, it shows that the app has been killed before, and you can do anything you want to handle.

sample code:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="id.gits.yourpackage">

    <application
        android:name=".App">
        <activity android:name=".SplashActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

SplashActivity:

class SplashActivity : AppCompatActivity() {
    override fun onCreate() {
        super.onCreate()
        doSomethingAfterAppKilled()
    }
}
nashihu
  • 750
  • 7
  • 17
1

After digging into this problem I found a solution that might help you:

All you need to do is check on the onDestroy method of your BaseActivity that is extended by all your activities whether the last running activity of the stack is from your package or not with the following code:

ActivityManager activityManager = (ActivityManager) getSystemService( ACTIVITY_SERVICE );

List<ActivityManager.RunningTaskInfo> taskList = activityManager.getRunningTasks( 10 );

if ( !taskList.isEmpty() )
    {
     ActivityManager.RunningTaskInfo runningTaskInfo = taskList.get( 0 );
      if ( runningTaskInfo.topActivity != null && 
              !runningTaskInfo.topActivity.getClassName().contains(
                    "com.my.app.package.name" ) )
         {
        //You are App is being killed so here you can add some code
         }
    }
1

I found a way that can detect app(contains Activity scenarios) kill: use ActivityLifecycleCallbacks to counter activity active number

There are some situations:

  • for User kill( use App switcher ): counter activity number/taskstack etc
  • (unspecify)for Android Framework kill(Low Memory etc):
  • (unspecify)for Native kill(Process.kill kill signal): use native
class StarterApplication: android.app.Application() {
var counterActivityCreate = 0
override fun onCreate() {
    super.onCreate()
    Log.d(TAG, "onCreate: ")

    registerActivityLifecycleCallbacks(object: android.app.Application.ActivityLifecycleCallbacks{
        override fun onActivityCreated(activity: android.app.Activity, savedInstanceState: android.os.Bundle?) {
            Log.d(TAG, "onActivityCreated: ${activity.javaClass.name}")
            counterActivityCreate++
        }

        override fun onActivityStarted(activity: android.app.Activity) {
            Log.d(TAG, "onActivityStarted: ${activity.javaClass.name}")
        }

        override fun onActivityResumed(activity: android.app.Activity) {
            Log.d(TAG, "onActivityResumed: ${activity.javaClass.name}")
        }

        override fun onActivityPaused(activity: android.app.Activity) {
            Log.d(TAG, "onActivityPaused: ${activity.javaClass.name}")
        }

        override fun onActivityStopped(activity: android.app.Activity) {
            Log.d(TAG, "onActivityStopped: ${activity.javaClass.name}")
        }

        override fun onActivitySaveInstanceState(activity: android.app.Activity, outState: android.os.Bundle) {
            Log.d(TAG, "onActivitySaveInstanceState: ${activity.javaClass.name}")
        }

        override fun onActivityDestroyed(activity: android.app.Activity) {
            Log.d(TAG, "onActivityDestroyed: ${activity.javaClass.name}")
            counterActivityCreate--
            if(counterActivityCreate == 0){
                Log.d(TAG, "onActivityDestroyed: all activity destroyed")

            }
        }

    })
}
Hpbbs
  • 11
  • 2
0

This might help many, who wants to know if the app is terminated or not The best way is to keep data in one static variable for eg: public static string IsAppAvailable;

the specialty about the static variable is that the data in the static variable contains till the app is in foreground or background, once the app is killed the data in the static variable is erased. Basically, the static variable is reinitialized when the app is freshly created

Create one static class file say Const

namespace YourProject
{
    public static class Const
    {
        public static string IsAppAvailable;
     }
}

In MainActivity

   protected override void OnResume()
    {
       if(string.IsNullOrWhiteSpace(Const.IsAppAvailable))
       {
          //Your app was terminated
       }
       Const.IsAppAvailable = "Available" 
    }

Hope this is helpful to the developers :) Happy coding

0

I found something that worked for me (in xiaomi), you have to make a class for example "MyObserver", and call this in your on create as follows: getLifecycle().addObserver(MyObserver(this)).

class MyObserver(var context: Context) : LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun disconnect() {
        Log.e("APP", "killed")
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun pause(){
        Log.e("APP","Paused") //para pausa
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun resume(){
        Log.e("APP","Resumed") //para retorno de pausa
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stop(){
        Log.e("APP","Stopped") // para cambio de actividad
    }
}
OVO Cuenta
  • 35
  • 4
-4

I have alternate idea.i have same problem like you.above methods not fix.my problem : "i want to clear all saved data entire app,when user completely close the app"

So, i added clear() & clear saved data(from shared preference or tinyDB) in Application class.