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.
I am a very enthusiastic Android developer who develops applications for devices powered by the Android operating system. I keep myself updated with the latest technologies available in Android.
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.
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
What is gt ?
This is autogenerated by tools. Please ignore, replace with “>” to “>”
What is gt? and plz re-write the code
got it it is “>”. THanks
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