How can a service listen for touch gestures/events?

I had this same problem and I've finally figured it out! Thanks to this post: Creating a system overlay window (always on top). You need to use an alert window instead of an overlay (and this also means you can use it in Andoid ICS):

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);

Then just attach a GestureListener in this manner:

GestureDetector gestureDetector = new GestureDetector(this, new AwesomeGestureListener());
View.OnTouchListener gestureListener = new View.OnTouchListener() {
      public boolean onTouch(View v, MotionEvent event) {
            return gestureDetector.onTouchEvent(event);
      }
};

overlayView.setOnTouchListener(gestureListener);

Yay!


Interesting question. I don't know how they did that and I found google group posts which tell me that there is no global touch listener. But I have an idea anyways...

I found this post where someone succeeds to display a popupwindow from a service. If I would make that popup transparent and fullscreen, I'm sure I could capture the touches since I'm allowed to set a touch interceptor.

Edit: Please report results when you try that, would be interesting to know if this works...


I tested every possible solution but nothing worked some didn't fired touch event which did they frozed the screen .

So I did some reverse engineering and now posting solution which works

  WindowManager.LayoutParams params = new android.view.WindowManager.LayoutParams(0, 0, 0, 0, 2003, 0x40028, -3);
        View mView = new View(this);

        mView.setOnTouchListener(this);

        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mView, params);

I tested this on API 21 and a nexus 5 and I was able to log, from a service, when a touch event was fired by the system. However, the data inside the MotionEvent object, for example coordinates, returns 0.0 when OUTSIDE of what seems to be my app's package.

Two sources integration, permission

I'm curious as to why the event.getX(), event.getY() and event.getPressure() return 0.0 when not in an activity of the app where the service lives.

Edit

This solution does not prevent other listeners from receiving the touch event capured by the service because of

public boolean onTouch(View v, MotionEvent e){
    Log.d(LOG_TAG, "Touch event captured");
    return false;      

By returning false, it allows other listeners to receive the event.

Edit2

Apparently, the input dispatcher in the OS will set the coordinates and pressure to 0 if the current activity and the listener do not share an UID, here is source