UPDATE:
So I figured out that it was because the MotionEvent was being changed after I passed it to the thread, the solution was this:
/**
* Standard override to get touch screen motion events.
*/
#Override
public boolean onTouchEvent(MotionEvent event) {
MotionEvent passMe = MotionEvent.obtain(event);
event.recycle();
return thread.doTouchEvent(passMe);
}
but somehow I end up with event and passMe having the same MotionEvent id, for some reason a new MotionEvent isn't created.
What did I do wrong? :(
---vvv OLD vvv---
I'm developing an Android app and I have this code here that adds any touch inputs of action type ACTION_DOWN to a queue:
/** Adds the touch event to the motionEventQueue for processing. */
public boolean doTouchEvent(MotionEvent event) {
//Only add the MotionEvent to the queue if we care about that kind of action.
if (event.getAction() == MotionEvent.ACTION_DOWN) {
motionEventQueue.add(event);
}
return true;
}
The problem is that this code here should make sure that only MotionEvents of action type ACTION_DOWN get into the queue, but somehow I'm ending up with MotionEvents of type ACTION_UP and others inside the queue.
Why is this happening? Looking at the debugger it appears that when they're added to the queue they are of type ACTION_DOWN but when it comes time to process the queue the action types seem to have changed somehow.
EDIT: Here is my onTouchEvent method:
/**
* Standard override to get touch screen motion events.
*/
#Override
public boolean onTouchEvent(MotionEvent event) {
return thread.doTouchEvent(event);
}
EDIT: Does it have to do with the fact that I'm using more than one thread? Is it unsynchronizing or something?
Events are recycled. You're passed a reference to the event, and you're adding a reference to your queue. The event will be recycled, so your reference points to a new event that was recycled using the old event. If you're lucky.
You shouldn't use the event after the execution of onTouchEvent has finished. If you need to store some of its data persistently, copy it to your own structure (or clone the event, if that's possible).
As to your other question - only the UI thread handles touch events, so having multiple threads shouldn't matter (unless of course you use those other threads to torpedo your queue).
Related
i create a system overlay app using this way
but i have a problem .... when i move my button to corner of screen, i can't touch system's view like Call button in the following image
image
how can i disable any touch in my button ? ( ignore my view's touch and touch system's view )
in somewhere i find this code but it isn't work
bl.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
Always visit developer.android.com first, it's really well documented with fundamental concepts.
The onTouch method will pass the event to the layer below it, if it returns false.
If you've extended a default touchable View class, you should use return super.onTouch()
Here's the link you're looking for:
https://developer.android.com/reference/android/view/View.OnTouchListener.html
I have created some activity which is transparent when some different app opens my activity starts and opens on top of that activity (Intent.FLAG_ACTIVITY_NEW_TASK).
What i am trying to achieve is what action happens on my activity will reflect to other activity.I mean when i scroll down underlaying view will scroll.
I could NOT do that i have used some flags combinations but it did not work.
I could not pass touch events both activities at the same time. It just works at one view, i need to do what happens on top (transparent) activity , underlaying activity has get to same events.
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
// window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
window.addFlags(WindowManager.LayoutParams.FLAG_SPLIT_TOUCH);
// window.addFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
//window.addFlags(WindowManager.LayoutParams.TYPE_PHONE);
setContentView(R.layout.trans);
final View v = getWindow().getDecorView().findViewById(android.R.id.content);
v.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.i("TAG", View !!!!!!!!");
return false;
}
});
This is not possible. You can neither inject input events to other apps' Activities nor can you receive their input events (known as tapjacking).
You cannot do that with touch events, I am also not sure why would you want to do so.
That said, you can use local broadcasts or EventBus but it is a really bad idea, catch touch events in one Activity and pass to the other one after that.
I have a Java class that pertains to mouse listeners that I'm wanting to convert over to my Android app but can't quite find the necessary events.
My Java app makes use of the following methods:
mouseClicked
mousePressed
mouseReleased
I'm wanting to do something similar however not with click events but touch events. I have come across OnTouchListener and did an override on the onTouch method.
What are the alternatives to mousePressed and mouseReleased?
Edit - (updated after Peter's response)
Are the following events correct:
ACTION_DOWN : mouseClicked
ACTION_MOVE : mousePressed
ACTION_UP : mouseReleased
EDIT - 2 Example Source
My Activity doesn't have any OnTouchListener at the moment because I was hoping I could keep all the touch logic in my View.
View:
/*Inside my View - Is it proper to do onTouch logic here?
Or should I be doing this from the Activity?*/
public class myView {
public boolean onTouch(MotionEvent event) {
switch(event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
//draw arrow when screen is simply touched
break;
case MotionEvent.ACTION_MOVE:
//Do Logic
break;
case MotionEvent.ACTION_UP:
//Do Logic
break;
}
}
}
The reason I am doing the logic in my View is because I have some variables that I would like to grab directly rather than creating multiple extra get methods.
Am I able to do it like this? Or will I have to override the onTouch method in my Activity and do the logic there?
All touch events (down, up, move, multitouch) are handled via 'onTouch'. See this tutorial: http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-3-understanding-touch-events/1775
If you want to register clicks on a View, implement and add an OnClickListener to it.
When you want to register touch events you need to implement the OnTouchListener and add it to that View.
Can someone walk me through the best way to do this? I want to make an interface that extends OnTouchListener. Instead of one meathod called onTouch(View view, MotionEvent e) i want 3 meathods; onPress() onMove() and onRelease(). The onPress meathod gets called when you press on the screen and the onMove gets called when you move your finger across the screen. onRelease gets called when you release your finger. All relevant answers are welcome.
You'd use the YourTouchListener provided by duffymo by extending your View class and adding a setYourTouchListener(YourTouchListener listener) method to this class.
You'd then override onTouchEvent(MotionEvent event) and call the relevant methods of your listener. Like so:
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
listener.onPress(this, event);
break;
case MotionEvent.ACTION_MOVE:
listener.onMove(this, event);
break;
case MotionEvent.ACTION_UP:
listener.onRelease(this, event);
break;
}
//this means that you have "used" this event. The ViewGroup will direct all further associated events straight here.
return true;
}
I would probably do essentially what CaspNZ posted, the only difference being that you shouldn't extend OnTouchListener in this case. Implementing an interface means that you must give an implementation for all of its methods, so in this case onTouch in addition to the three that you are creating, which is redundant. And of course if you still end up needing onTouch for something, you can always implement OnTouchListener in addition to YourTouchListener.
You can use GestureListener and use onFling(...) method, which gives you possibility (MotionEvent e1 and MotionEvent e2) to measure initial touch (on press) and final touch (release) and based on this you do your job. Also provides velocity of MotionEvent along x and y axis, measure pressure applied on the screen, etc. This will cut your time on writing the whole interface you are about to do.
For an application I am writing, I want to invoke a certain action once the user lifted his finger off the screen. I understood I need to check if event.getAction() is ACTION_UP, but all I get from getAction() is ACTION_DOWN. My code looks like this:
menu = new MenuView(this);
menu.setBackgroundColor(Color.WHITE);
menu.setKeepScreenOn(true);
...
setContentView(menu);
menu.requestFocus();
...
public class MenuView extends View
{
...
public MenuView(Context context)
{
super(context);
setFocusable(true);
}
Anybody knows what is the reason for the problem?
Thank you in advance.
make sure onTouch returns true which tells the os your listener handles the touch event.
from the docs: onTouch() - This returns a boolean to indicate whether your listener consumes this event. The important thing is that this event can have multiple actions that follow each other. So, if you return false when the down action event is received, you indicate that you have not consumed the event and are also not interested in subsequent actions from this event. Thus, you will not be called for any other actions within the event, such as a finger gesture, or the eventual up action event.
http://developer.android.com/reference/android/view/View.html#onTouchEvent%28android.view.MotionEvent%29