Getting all MotionEvents with WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - android

My question refers directly to this question. The answer to that question shows how one can create a ViewGroup, embed it inside a WindowManager, and allow the WindowManager to catch MotionEvents through onTouchEvent(MotionEvent event). WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH is the flag that allows this this ViewGroup to receive MotionEvents. However, according to documentation, this flag
...will not receive the full down/move/up gesture
I want to know if there's a work-around or a way so that I can get all touch events including down, move, and up. A proof of concept is in the app Wave Launcher which uses the same concept but is able to receive more than just a single ACTION_OUTSIDE event.

No you can not, and that is very much by design.
Wave Launcher doesn't do this, it has a UI element where you start your touch gesture and then as with standard even dispatching all touch events are delivered to the window of the first down point until the final up.

I realize this is an old question, but I've stumbled across it while trying to accomplish something similar. I've also found this, hopefully it is helpful to someone: http://www.section465.com/code_OverlayView/
To create an overlay view, when setting up the LayoutParams you need
to set the type to TYPE_SYSTEM_OVERLAY and use the flag
FLAG_WATCH_OUTSIDE_TOUCH. This presents a problem because as the
Android documentation states: "you will not receive the full
down/move/up gesture, only the location of the first down as an
ACTION_OUTSIDE." In order to receive the full array of touch events
you need to use the TYPE_SYSTEM_ALERT type, but this causes the
overlay to take over the screen and stop interaction with other
elements. The solution is to use both TYPE_SYSTEM_OVERLAY and
TYPE_SYSTEM_ALERT and switch between them by changing the type of the
LayoutParams as needed.

Related

Passing clicks events from floating app to covered app

I have a floating app which works perfectly.
I am using OnTouchListener to catch events since I need to use the GestureDetector for swipes etc.
My only problem is that sometimes I wish to ignore certain events on the view.
In this case the view is invisible but not "gone" because I need it to accept certain gestures but not others.
I can't seem to be able to do that.
Returning false from "onTouch" simply doesn't work.
I checked that by experiment by disabling the GestureDetector and simply always returning false just to see what would happen. Result was nothing going through.
Is it even possible to pass a click through to a covered app?
Due to security reasons it's not possible to record and pass a click below (essentially allows building a keylogger).
Best you can do is have your floating window small enough to start the touch but not cover too much of the screen below.

Android Wear Overlay Pass on Touch Events

I have an Android Wear app in which I use a transparent overlay view to recieve touch events. I need to be able to receive all touch events that happen anywhere on the screen, and also be able to see their coordinates.
All research I have found says that I cannot recieve all touch events and pass them on. However, Wear Mini Launcher and Swipify are both doing something like this.
Here is where I have looked:
Android overlay to grab ALL touch, and pass them on?
https://stackoverflow.com/questions/19356834/overlay-view-which-intercepts-some-events
Android - Intercept and pass on all touch events
Android : Multi touch and TYPE_SYSTEM_OVERLAY
Creating a system overlay window (always on top)
Getting the View that is receiving all the touch events
Android Jelly Bean service that receives all touch events
TYPE_SYSTEM_OVERLAY in ICS
Overlay App that reacts only on some touch events
This must be possible to do somehow. Maybe an overlay view is not the right way to approach this? Any pointers?
I had quite a bit of trouble with this as well using the same links that you provided. But then I found this: http://www.piwai.info/chatheads-basics/
It's basically the same as the other solutions, except that the arguments to the WindowManager LayoutParams are TYPE_PHONE and FLAG_NOT_FOCUSABLE.
Not only did this solution work for me (I was testing on an LG Urbane), the onTouchEvent callback had all the actions (down, move, and up), which the other solutions said you wouldn't get.
Since all the touch events are passed through the view, in theory we can use gesture detectors to get callbacks for things like double taps and flings. I haven't tried this yet, though.
Regardless, the above link should get you past the initial problems you're facing.

TYPE_SYSTEM_OVERLAY in ICS

In Honeycomb I was able to create a system overlay with TYPE_SYSTEM_OVERLAY and receive touches with FLAG_WATCH_OUTSIDE_TOUCH.
Now ICS has changed something. I can still create the system overlay, but i can't get touches.
Now, i am able to create the same with TYPE_SYSTEM_ALERT and get touches, but it just catches the touchevents, and not passing them on like in Honeycomb.
Any idea's?
Kind regards
To create an overlay view, when setting up the LayoutParams
DON'T set the type to TYPE_SYSTEM_OVERLAY.
Instead set it to TYPE_PHONE.
Use the following flags:
FLAG_NOT_TOUCH_MODAL
FLAG_WATCH_OUTSIDE_TOUCH
FLAG_NOT_TOUCH_MODAL << I found this one to be quite important. Without it, focus is given to the overlay and soft-key (home, menu, etc.) presses are not passed to the activity below.
Everything you describe is true. It is presumably to tighten up security, as the former behavior was the source of tapjacking attacks. I wrote a blog post recently about this change.
Any idea's?
Don't use either of them.

Android : Multi touch and TYPE_SYSTEM_OVERLAY

I am trying to get multiple touch events on a system overlay view, but am only receiving the MotionEvent.ACTION_OUTSIDE event.
Is there any possible way of getting multiple touch events on a system overlay?
Any examples or links would be very helpful.
To create an overlay view, when setting up the LayoutParams you need to set the type to TYPE_SYSTEM_OVERLAY and use the flag FLAG_WATCH_OUTSIDE_TOUCH. This presents a problem because as the Android documentation states:
you will not receive the full down/move/up gesture, only the location of the first down as an ACTION_OUTSIDE.
In order to receive the full array of touch events you need to use the TYPE_SYSTEM_ALERT type, but this causes the overlay to take over the screen and stop interaction with other elements. The solution is to use both TYPE_SYSTEM_OVERLAY and TYPE_SYSTEM_ALERT and switch between them by changing the type of the LayoutParams as needed.
This is accomplished by:
Watch for the ACTION_OUTSIDE motion event.
When it occurs, test if it occured within the overlay.
If it did, switch the LayoutParams type to TYPE_SYSTEM_ALERT
Once the interaction with the overlay is complete, switch back to TYPE_SYSTEM_OVERLAY
Repeat
The one thing to keep in mind is that the ACTION_OUTSIDE motion event is always passed on to the rest of the elements on the screen. So, for example, if the overlay is on top of a button, that button will also receive the motion event and there is no way to stop it.
Also make sure you add the SYSTEM_ALERT_WINDOW permission to the mainifest file.
I've posted the complete solution here:
http://www.jawsware.mobi/code_OverlayView/ (UPDATED)
It includes all the source code and a link to download the entire example project.
Update for Android 4.0 - 1/3/2013
To create an overlay view, when setting up the LayoutParams DON'T set the type to TYPE_SYSTEM_OVERLAY.
Instead set it to TYPE_PHONE.
Use the following flags:
FLAG_NOT_TOUCH_MODAL
FLAG_WATCH_OUTSIDE_TOUCH
FLAG_NOT_TOUCH_MODAL << I found this one to be quite important. Without it, focus is given to the overlay and soft-key (home, menu, etc.) presses are not passed to the activity below.
Also, the previous link (above) has been updated to reflect this update.
Starting from Android 4.x, Android team Android team fixed a potential
security problem by adding a new function adjustWindowParamsLw() in which it
will add FLAG_NOT_FOCUSABLE, FLAG_NOT_TOUCHABLE and remove FLAG_WATCH_OUTSIDE_TOUCH flags for TYPE_SYSTEM_OVERLAY window.
That's TYPE_SYSTEM_OVERLAY window won't receive any touch event on ICS platform.
Updated: 2016/5/4
TYPE_TOAST cannot receive touch events on Android 4.0~4.3. It's the same as TYPE_SYSTEM_OVERLAY. On Android 4.4+, TYPE_TOAST removed from the excluded list, so you can use TYPE_TOAST to receive touch events on Android 4.4+ devices.

When would ACTION_OUTSIDE be triggered?

I don't understand when ACTION_OUTSIDE is triggered. Please give me an example.
The doc's give this cryptic description:
Constant for getAction(): A movement
has happened outside of the normal
bounds of the UI element. This does
not provide a full gesture, but only
the initial location of the
movement/touch.
http://developer.android.com/reference/android/view/MotionEvent.html#ACTION_OUTSIDE
I believe it is only used for clicking outside of the current activity (for example a dialog). Check out WindowManager.LayoutParams

Categories

Resources