Auto Logout or Expire the session after 5 minutes of user inactivity

Sharing is caring!

Sometimes we need to log out the user or expire his session if he did not perform any interaction with the app for 5 minutes or even If he locks the screen from the lock button. This can be implemented very easily by maintaining a thread(Waiter) which will give alert once 5 minutes are over after last user interaction.

First, create a file AppLockManager like this.

public class ApplockManager {
    private static ApplockManager instance;
    private DefaultApplock currentAppLocker;

    public static ApplockManager getInstance() {
        if (instance == null) {
            instance = new ApplockManager();
        }
        return instance;
    }

    public void enableDefaultAppLockIfAvailable(Application currentApp) {

        currentAppLocker = new DefaultApplock(currentApp);

    }

    public void updateTouch(){
        currentAppLocker.updateTouch();
    }
}

Then create a file DefaultApplock by extending ActivityLifeCycleCallbacks this will provides with lifecycle methods like onActivityResume and onActivityPause etc.

public class DefaultApplock implements Application.ActivityLifecycleCallbacks {

    final String TAG = DefaultApplock.class.getSimpleName();

    private Application mCurrentApp;

    private long WAIT_TIME = 5*60*1000;
    private Waiter waiter;
    private Date mLostFocusDate;

    public DefaultApplock(Application app) {
        super();
        mCurrentApp = app;

        //Registering Activity lifecycle callbacks
        mCurrentApp.unregisterActivityLifecycleCallbacks(this);
        mCurrentApp.registerActivityLifecycleCallbacks(this);
    }

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

    }

    @Override
    public void onActivityStarted(Activity activity) {

    }

    @Override
    public void onActivityResumed(Activity activity) {
        // for UserInactivity
        if(waiter!=null) {
            waiter.stopThread();
        }
        waiter=new Waiter(activity,WAIT_TIME);
        waiter.start();

        // for Screen lock
        if (shouldShowUnlockScreen()) {
            Log.d(TAG, "time over");
            //

            Intent intent = new Intent(activity.getApplicationContext(), ActivitySplashScreen.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
            Log.d(TAG, "changing mLostFocus to null");
            mLostFocusDate = null;
            activity.getApplicationContext().startActivity(intent);

        }
    }

    private boolean shouldShowUnlockScreen() {
        Boolean isvalid = false;
        if (mLostFocusDate == null) {
            isvalid = false;
        } else {
            Log.d(TAG, "Timeout ->"+timeSinceLocked());
            if (timeSinceLocked() >= (WAIT_TIME/1000)) {
                isvalid = true;
            } else {
                mLostFocusDate = null;
            }
        }
        Log.d(TAG, isvalid.toString());
        return isvalid;
    }

    private int timeSinceLocked() {
        return Math.abs((int) ((new Date().getTime() - mLostFocusDate.getTime()) / 1000));
    }


    @Override
    public void onActivityPaused(Activity activity) {
        if(waiter!=null) {
            waiter.stopThread();
        }
        mLostFocusDate = new Date();
    }

    @Override
    public void onActivityStopped(Activity activity) {

    }

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

    }

    @Override
    public void onActivityDestroyed(Activity activity) {

    }

    public void updateTouch() {
        if(waiter!=null) {
            waiter.touch();
        }
        mLostFocusDate = new Date();
    }
}

Now Create a Waiter thread which will keep a record of the time that is elapsed after the last user interaction and will provide an alert once that time exceeds 5 minutes.

public class Waiter extends Thread
{
    private static final String TAG=Waiter.class.getName();
    private long lastUsed;
    private long period;
    private boolean stop = false;
    private Context mContext;

    public Waiter(Context context,long period) {
        this.period=period;
        stop=false;
        mContext = context;
    }

    public void run() {
        long idle=0;
        this.touch();
        Log.d("Value of stop",String.valueOf(stop));
        do
        {
            idle=System.currentTimeMillis()-lastUsed;
//            Log.d(TAG, "Application is idle for "+idle +" ms");
            try
            {
                Thread.sleep(2000); //check every 5 seconds
            }
            catch (InterruptedException e)
            {
                Log.d(TAG, "Waiter interrupted!");
            }
            if(idle > period)
            {
                idle=0;
                //do something here - e.g. call popup or so

                // Perform Your desired Function like Logout or expire the session for the app.
                stopThread();
            }
        }
        while(!stop);
        Log.d(TAG, "Finishing Waiter thread");
    }

    public synchronized void touch() {
        lastUsed=System.currentTimeMillis();
    }

    public synchronized void forceInterrupt() {
        this.interrupt();
    }

    public synchronized void setPeriod(long period)
    {
        this.period=period;
    }

    public synchronized void stopThread() {
        stop = true;
    }

    public synchronized void startThread() {
        stop = false;
    }

    public synchronized void closeThread() {
        // Perform Your desired Function like Logout or expire the session for the app.
        stopThread();
    }



}

Now in your base activity Override UserInteraction Method to update the timer for the waiter thread. In this method we will start the timer every time user perform any interaction with the app. getApp() function will be used to get applicationContext().

public ABFSApplication getApp() {
    return (ABFSApplication) this.getApplication();
}

@Override
public void onUserInteraction() {
    super.onUserInteraction();
    getApp().touch();
    Log.d("TAG", "User interaction to " + this.toString());
}

Now lastly in your application file write this method touch to update userInteraction.

public void touch() {
    ApplockManager.getInstance().updateTouch();
}

Please do subscribe email to get all newsletters of this blog and if you feel that this post will help you to understand then do not forget to subscribe, share and comment below.

4.3 7 votes
Article Rating

Similar Posts

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

7 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Ravi

Hi Abhishek,

will this work if my app is in kiosk mode – basically app will be the launcher and there will never be screen lock happening unless done purposely. My expectation is if user doesn’t have any event called- click or touch in app for 5 mins than user should be logged out . please help.

Timi

Thanks for your solution. I’m pretty new in Android development. How do i call my logout method in the base presenter class of my base activity

Neha

What is gt ?

admin

This is autogenerated by tools. Please ignore, replace with “>” to “>”

Saurabh

What is gt? and plz re-write the code

saurabh

got it it is “>”. THanks

Martins

Hello thank you for your solution. In my case I don’t want to take the user to a login screen but rather show a dialog box requesting for a pin not just for inactivity at foreground but when the user goes to the background and returns back to the foreground