0

I'm trying to create a View that will be used to Log all MotionEvent. This View is in a Service() which is linked to the App from where I need the events to be logged.

My problem is that when this View comes on top of the App, as needed, all the events are consumed in this View.

Is there a way to prevent this View to consume the event, and let the View on the back to consume it ?

Here is the code of the Service()

class GestureTrackViewService : Service(), View.OnTouchListener {

    var mWindowManager: WindowManager? = null
    var mDummyView: LinearLayout? = null

    override fun onBind(p0: Intent?): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val params = WindowManager.LayoutParams(
                1080, /* width */
                1920, /* height */
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
                        WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
                        WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSPARENT)
        params.gravity = Gravity.START or Gravity.TOP
        mDummyView!!.isFocusable = false
        mDummyView!!.isClickable = false
        mWindowManager!!.addView(mDummyView, params)
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onCreate() {
        mWindowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        mDummyView = LinearLayout(this)
        val params = WindowManager.LayoutParams(1, WindowManager.LayoutParams.MATCH_PARENT)
        mDummyView!!.layoutParams = params
        mDummyView!!.setOnTouchListener(this)

        super.onCreate()
    }

    override fun onTouch(p0: View, p1: MotionEvent): Boolean {
        Log.e("SERVICE", "X: ${p1.rawX} || Y: ${p1.rawY}")
        mDummyView!!.requestDisallowInterceptTouchEvent(false)
        return false
    }
}
Mahesh Babariya
  • 4,560
  • 6
  • 39
  • 54
Sylvain GIROD
  • 836
  • 1
  • 11
  • 23
  • You need to rethink what you're trying to do from the ground up. Your approach is totally wrong. Androiud works on the idea of touch capture- the first view to respond and claim an event owns all the subsequent events for that touch, with a complicated override system for parents. What you're trying to do will never work. – Gabe Sechan Mar 27 '17 at 20:45
  • Well, I was afraid of this. My final goal is to log all events (and their position) in a View. I tried by creating a custom View which logs the events, but it doesn't work if the user does a gesture on an interactive component (Button, EditText...). Do you have a solution to Log even in View childs without modifying the components code ? – Sylvain GIROD Mar 27 '17 at 20:48
  • 1
    On the root view, override onInterceptTouchEvent to do it, and always return false. That should work, but I won't promise you won't see weird interactions with any view that scrolls or moves. You won't be able to do it from a Service or another app. – Gabe Sechan Mar 27 '17 at 20:54
  • Thanks for your help, you put me in the good way ! the method to be used by root view was dispatchTouchEvent instead of onInterceptTouchEvent, but now it works well ! – Sylvain GIROD Mar 27 '17 at 22:10

1 Answers1

0

What I wanted to achieve is not possible using a Service().

Instead, I used a custom root View and implemented dispatchTouchEvent()

Source of this response here : onInterceptTouchEvent only gets ACTION_DOWN

Community
  • 1
  • 1
Sylvain GIROD
  • 836
  • 1
  • 11
  • 23