Search code examples
androiduser-inactivity

How to detect user inactivity in Android


User start my app and logs in.
Selects Session Timeout to be 5 mins.
Does some operations on the app. (all in foreground)
Now User bring Myapp to background and starts some other app.
----> Count down timer starts and logs out user after 5 mins
OR user turns the screen OFF.
----> Count down timer starts and logs out user after 5 mins

I want the same behavior even when the app is in the foreground but user doesn't interact with the app for a long-time say 6-7 mins. Assume the screen is ON all the time. I want to detect kind of user inactivity (No interaction with app even though the app is in the foreground) and kick start my count down timer.


Solution

  • public class MyApplication extends Application {
          private int lastInteractionTime;
          private Boolean isScreenOff = false; 
          public void onCreate() {
            super.onCreate();
            // ......   
            startUserInactivityDetectThread(); // start the thread to detect inactivity
            new ScreenReceiver();  // creating receive SCREEN_OFF and SCREEN_ON broadcast msgs from the device.
          }
    
          public void startUserInactivityDetectThread() {
            new Thread(new Runnable() {
              @Override
              public void run() {
                while(true) {
                  Thread.sleep(15000); // checks every 15sec for inactivity
                  if(isScreenOff || getLastInteractionTime()> 120000 ||  !isInForeGrnd)
                    {
                      //...... means USER has been INACTIVE over a period of
                      // and you do your stuff like log the user out 
                    }
                  }
              }
            }).start();
          }
    
          public long getLastInteractionTime() {
            return lastInteractionTime;
          }
    
          public void setLastInteractionTime(int lastInteractionTime) {
            this.lastInteractionTime = lastInteractionTime;
          }
    
          private class ScreenReceiver extends BroadcastReceiver {
    
            protected ScreenReceiver() {
               // register receiver that handles screen on and screen off logic
               IntentFilter filter = new IntentFilter();
               filter.addAction(Intent.ACTION_SCREEN_ON);
               filter.addAction(Intent.ACTION_SCREEN_OFF);
               registerReceiver(this, filter);
            }
    
            @Override
            public void onReceive(Context context, Intent intent) {
              if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                isScreenOff = true;
              } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
                isScreenOff = false;
              }
            }
          }
        }
    

    isInForeGrnd ===> logic is not shown here as it is out of scope of the question

    You can wake the lock to the cpu by using the device code below-

      if(isScreenOff || getLastInteractionTime()> 120000 ||  !isInForeGrnd)
        {
          //...... means USER has been INACTIVE over a period of
          // and you do your stuff like log the user out 
    
          PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    
          boolean isScreenOn = pm.isScreenOn();
          Log.e("screen on.................................", "" + isScreenOn);
    
          if (isScreenOn == false) {
    
            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "MyLock");
    
            wl.acquire(10000);
            PowerManager.WakeLock wl_cpu = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyCpuLock");
    
            wl_cpu.acquire(10000);
          }
        }