How do I detect if the user has left my app?

后端 未结 6 1009
情话喂你
情话喂你 2020-12-02 15:36

I am developing an Android app and I want to detect when the user exits my app either by clicking the Back button or the Home button.

Also, an event like onIn

相关标签:
6条回答
  • 2020-12-02 16:15

    Yes, check the lifecycle of the app - when a user minimizes or leaves a couple of methods get called onPause() onStop() and onDestroy()

    http://developer.android.com/reference/android/app/Activity.html

    0 讨论(0)
  • 2020-12-02 16:16

    If your activity is the last in the stack then detecting a back button with onKeyDown would solve 1/2 of this

    The home key is a little trickier, there is no absolute method but you could do something like this which works for my simple needs.

    The onUserLeaveHint is called according to the documentation when the user clicks the home button OR when something interrupts your application (like an incoming phone call) so to guess which it is you use the onUserInteraction method to stamp the last user interaction time.

    Now if that precedes the onUserLeaveHint closely enough you can assume (not guaranteed but has worked for me so far) that the home button was the reason your application is being pushed into the background (exiting)

    Not sure what your intent is in catching the home button, anyway here is a simplistic way to do that, I use a 100ms fence around the two events which I have found has always worked for me. NOTE: I have only tested on a handful of phones, like all things in Android your mileage will vary dependent on OS / Hardware (heck even the stuff that's documented and supposed to work sometimes doesn't)

    long userInteractionTime = 0;
    
    @Override
    public void onUserInteraction() {
        userInteractionTime = System.currentTimeMillis();
        super.onUserInteraction();
        Log.i("appname","Interaction");
    }
    
    @Override
    public void onUserLeaveHint() {
        long uiDelta = (System.currentTimeMillis() - userInteractionTime);
    
        super.onUserLeaveHint();
        Log.i("bThere","Last User Interaction = "+uiLag);
        if (uiDelta < 100)
            Log.i("appname","Home Key Pressed");    
        else
            Log.i("appname","We are leaving, but will probably be back shortly!");  
    }
    
    0 讨论(0)
  • 2020-12-02 16:17

    With the help of Application.ActivityLifecycleCallbacks you can track which activity is destroying and new activity is starting but when user swipe or back button(on last stack) then postdelayed will not call and also Activitystop and destroy will always call when you're inside your application if you want to catch user swipe or back button(on last stack) then this code will work.

    public class Yourapp extends Application implements Application.ActivityLifecycleCallbacks {
    
        private Activity currentActivity; 
        private Handler closecheckhandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    //do whatever you want
                    default:
                        super.handleMessage(msg);
                }
            }
        };
        @Override
        public void onCreate() {
            super.onCreate();
    
            registerActivityLifecycleCallbacks(this);
    
        }
    
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    
        }
    
        @Override
        public void onActivityStarted(Activity activity) {
    
        }
    
        @Override
        public void onActivityResumed(Activity activity) {
            currentActivity = activity;
    
        }
    
        @Override
        public void onActivityPaused(Activity activity) {
    
        }
    
        @Override
        public void onActivityStopped(Activity activity) {
    
        }
    
        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    
        }
    
        @Override
        public void onActivityDestroyed(Activity destroActivity) {
          if (currentActivity.equals(destroActivity)) {
                closecheckhandler.sendEmptyMessage(//Custom Code);
            } else {
                //do whatever you want
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 16:21

    another option that you might consider is to check for the back button or home key press. This is done by overriding the onKeyDown() , listen for the back key/home key and override the default behaviour.

    I've found a similar question that might help you out.

    Android: Prompt user to save changes when Back button is pressed

    Cheers

    0 讨论(0)
  • 2020-12-02 16:31

    Note: This only works if your target is >= API14


    You can also use Application.registerActivityLifecycleCallbacks() and when any activity pauses post a delayed Runnable (that will invoke when user lefts app) to Handler. When activities are created/started/resumed you remove that Runnable from Handler. So when you navigate inside your app you always cancel that Runnable, but if another activity not from your app is activated - the Runnable will be invoked.

    I used this to logout user when he lefts my app, here's code for callbacks:

    public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {
    
        private Handler handler;
        private Runnable runLogout = new Runnable() {
            @Override
            public void run() {
                //logoutUser()
            }
        };
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            registerActivityLifecycleCallbacks(this);
            handler = new Handler(getMainLooper());
        }
    
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            handler.removeCallbacks(runLogout);
        }
    
        @Override
        public void onActivityStarted(Activity activity) {
            handler.removeCallbacks(runLogout);
        }
    
        @Override
        public void onActivityResumed(Activity activity) {
            handler.removeCallbacks(runLogout);
        }
    
        @Override
        public void onActivityPaused(Activity activity) {
            handler.postDelayed(runLogout, 1000);
        }
    
        @Override
        public void onActivityStopped(Activity activity) {
    
        }
    
        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    
        }
    
        @Override
        public void onActivityDestroyed(Activity activity) {
    
        }
    }
    

    However, Runnable will run not in the context of activity lifecycle, so to use this in activity you would need to set and check some application-wide flag or broadcast an intent.

    0 讨论(0)
  • 2020-12-02 16:34

    The onUserLeaveHint is called according to the documentation when the user clicks the home button OR when something interrupts your application (like an incoming phone call) so to guess which it is you use the onUserInteraction method to stamp the last user interaction time.

    Just a small correction to the answer Idistic gave - OnUserLeaveHint() is not called when your activity is interrupted by an incoming call. Here is the snippet from Android documentation -

    Called as part of the activity lifecycle when an activity is about to go into the background as the result of user choice. For example, when the user presses the Home key, onUserLeaveHint() will be called, but when an incoming phone call causes the in-call Activity to be automatically brought to the foreground, onUserLeaveHint() will not be called on the activity being interrupted.

    0 讨论(0)
提交回复
热议问题