简体   繁体   中英

How can we detect the Android app killed by user or the System?

Is it possible to detect the Android App killed or exit by the user?

I try to use ActivityLifecycleCallbacks registerred in the Application class to detect it by assing an int parameter and increasing it in onActivityCreated like below; but it does not work.
I think the Android Service in my App makes this global counter variable (defined in a singleton class) not killed although the app has been killed.
It starts with zero only the first time when the app first start, then every app restart it has the the last value as the last time the app has been killed and never has a value of zero again.

Another question is that how can we release the global values to their initial values when the app killed that uses Android Service?

Singleton Class which has the global activity counter

public class SingletonClass {

    public int created_activity_number;

    private static volatile SingletonClass instance = null;

    private SingletonClass() {

    }

    public static SingletonClass getInstance() {
        if (instance == null) {
            synchronized (SingletonClass.class) {
                // Double check
                if (instance == null) {
                    instance = new SingletonClass();
                }
            }
        }
        return instance;
    }
}   

ActivityLifecycleCallbacks class

 public class MyLifecycleHandler implements Application.ActivityLifecycleCallbacks {

            private static int created;

            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                SingletonClass.getInstance().created_activity_number++;
            }

            @Override
            public void onActivityStarted(Activity activity) {

            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {

            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {

            }
        }

In any Activity I use below condition to check if the activity is the first created acitivy when the app starts.

// Enter this condition only one time no mattter how many times the application killed by the user end starts again.
if (SingletonClass.getInstance().created_activity_number == 1) {
            // Yes, it is the first created activiy 
}

I had the same problem, use this class

public class Foreground implements Application.ActivityLifecycleCallbacks {

public static final long CHECK_DELAY = 500;
public static final String TAG = Foreground.class.getName();

public interface Listener {

    public void onBecameForeground();

    public void onBecameBackground();

}

private static Foreground instance;

private boolean foreground = false, paused = true;
private Handler handler = new Handler();
private List<Listener> listeners = new CopyOnWriteArrayList<Listener>();
private Runnable check;

/**
 * Its not strictly necessary to use this method - _usually_ invoking
 * get with a Context gives us a path to retrieve the Application and
 * initialise, but sometimes (e.g. in test harness) the ApplicationContext
 * is != the Application, and the docs make no guarantees.
 *
 * @param application
 * @return an initialised Foreground instance
 */
public static Foreground init(Application application){
    if (instance == null) {
        instance = new Foreground();
        application.registerActivityLifecycleCallbacks(instance);
    }
    return instance;
}

public static Foreground get(Application application){
    if (instance == null) {
        init(application);
    }
    return instance;
}

public static Foreground get(Context ctx){
    if (instance == null) {
        Context appCtx = ctx.getApplicationContext();
        if (appCtx instanceof Application) {
            init((Application)appCtx);
        }
        throw new IllegalStateException("Foreground is not initialised and cannot obtain the Application object");
    }
    return instance;
}

public static Foreground get(){
    if (instance == null) {
        throw new IllegalStateException("Foreground is not initialised - invoke at least once with parameterised init/get");
    }
    return instance;
}

public boolean isForeground(){
    return foreground;
}

public boolean isBackground(){
    return !foreground;
}

public void addListener(Listener listener){
    listeners.add(listener);
}

public void addListenerUnique(Listener listener){
    if(!listeners.contains(listener)){
        listeners.add(listener);
    }
}

public void removeListener(Listener listener){
    listeners.remove(listener);
}

@Override
public void onActivityResumed(Activity activity) {
    paused = false;
    boolean wasBackground = !foreground;
    foreground = true;

    if (check != null)
        handler.removeCallbacks(check);

    if (wasBackground){
        Log.i(TAG, "went foreground");
        for (Listener l : listeners) {
            try {
                l.onBecameForeground();
            } catch (Exception exc) {
                Log.e(TAG, "Listener threw exception!", exc);
            }
        }
    } else {
        Log.i(TAG, "still foreground");
    }
}

@Override
public void onActivityPaused(Activity activity) {
    paused = true;

    if (check != null)
        handler.removeCallbacks(check);

    handler.postDelayed(check = new Runnable(){
        @Override
        public void run() {
            if (foreground && paused) {
                foreground = false;
                Log.i(TAG, "went background");
                for (Listener l : listeners) {
                    try {
                        l.onBecameBackground();
                    } catch (Exception exc) {
                        Log.e(TAG, "Listener threw exception!", exc);
                    }
                }
            } else {
                Log.i(TAG, "still foreground");
            }
        }
    }, CHECK_DELAY);
}

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

@Override
public void onActivityStarted(Activity activity) {}

@Override
public void onActivityStopped(Activity activity) {}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

@Override
public void onActivityDestroyed(Activity activity) {}
}

Init it in youur application class

Foreground.init(this);

And then use the listener to know app state

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM