Android

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

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

Recent Posts

Hide your production API key or any sensitive data in Android

Hi everyone, In this article, we are going to learn how to hide the production… Read More

2 years ago

How to handle the localisation or multi language support in android with examples?

Hello everyone, Today in this article, we are going to learn about localisation to support… Read More

2 years ago

How to convert any callback to Coroutines and use them in Kotlin Android?

Hello everyone, In this article, we are going to learn something to handle the callback… Read More

2 years ago

Request Permission Launcher with Kotlin in Android

In this article, we are learning about the run time permissions for request permission launchers.… Read More

2 years ago

Implement the SMS User Consent API and SMS Retriever API in Android

Hello everyone. In my last tutorial, we learned about the Jetpack Compose introduction and about applying the… Read More

3 years ago

Jetpack Compose Coroutine flow with LiveData/ViewModel in Android

Hello everyone, In this article, we are going to learn about the Jetpack Compose with… Read More

3 years ago