Search code examples
androidandroid-servicebackground-serviceforeground-service

How do I check user inactivity while my app isn't on foreground


My app will be running in the background and will alert the user if he isn't active on the device after 10 seconds. I cannot use the following method since the screen is supposed to be kept on all the time.

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();

Another method I found is overriding OnUserInteraction() on activity. But it seem to only work on our app's activity. What I want is to know if the user is interacting even if the app is not in foreground ie, there's no user interface. Is there any specific method to do this without using the screen timeout? Is it possible to know if my device is inactive using a service?


Solution

  • Well I found a way myself, thanks for the suggestions guys. Use a Service which sets up an overlay using WindowManager with LayoutParams(0,0,0,0) and then use WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH flag. This will return a MotionEvent called OUTSIDE_TOUCH, Which helped me to detect touch anywhere on screen even if my app isn't on foreground.

    int overlayType = Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_SYSTEM_ALERT : WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
            WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                    0, 0, 0, 0,
                    overlayType,
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
                            WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                    PixelFormat.TRANSLUCENT);
            wm = (WindowManager) getSystemService(WINDOW_SERVICE);
            touchListenerView = new View(this);
            touchListenerView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    handleInactive(event);
                    return false;
                }
            });
            wm.addView(touchListenerView, params);
    

    I am able to use this and a handler.postDelayed() to find out if my device is active or inactive within a specific time.