laszlo
laszlo

Reputation: 624

Detecting touch events in overlay and passing them further

I want to make an overlay gesture detector that will be displayed above all other apps. The overlay will be started from a Service.

I've made sample service just to check if touch event from touching overlaid icon can be somehow recorded and dispatched further to currently active app:

class GestureDetectorService : Service() {
override fun onBind(intent: Intent?): IBinder? = null

val windowManager: WindowManager
    get() = getSystemService(Context.WINDOW_SERVICE) as WindowManager

var iv: AppCompatImageView? = null

override fun onCreate() {
    super.onCreate()
    iv = AppCompatImageView(this)
    iv?.setImageResource(R.drawable.icon)

    iv?.setOnTouchListener { view, motionEvent ->
        when (motionEvent.action) {
            MotionEvent.ACTION_DOWN -> {
                Log.d("Click", "From icon")
                false
            }
            else -> false
        }
    }

    val params: WindowManager.LayoutParams = WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT
            , WindowManager.LayoutParams.WRAP_CONTENT
            , WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
            or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
            or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
            or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
            or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
            , PixelFormat.TRANSLUCENT)

    params.gravity = Gravity.TOP or Gravity.LEFT
    params.x = 100
    params.y = 100

    windowManager.addView(iv, params)
}

override fun onDestroy() {
    super.onDestroy()
    iv.let { windowManager.removeView(iv) }
}
}

no luck.

let's say I want to detect when user will perform a Flingof certain velocity, or 'draw' certain shape on the screen, which would trigger for example launching of notepad.

But I don't want any of this to block normal app interaction, user must be able to interact with whatever app is launched normally.

Concise answer in Kotlin would be super nice, but if you will come up with something in Java, that also would be great.

Upvotes: 1

Views: 813

Answers (1)

CommonsWare
CommonsWare

Reputation: 1006674

Fortunately, this is not possible, except perhaps on rooted devices or via custom firmware.

What you are describing is a tapjacking attack: spying on user input while passing that same input along so it has normal effects. This has been blocked for privacy and security reasons since Android 4.0.

Upvotes: 2

Related Questions