Bitwise operators android - android

I'm new to bitwise operator, I don't know what are they use for, but I know the following:
5 & 3 = 1
because
0101 & 0011 = 0001
So yeah, I understand that we multiply each bit pair like 1 x 0 = 0, 1 x 1 = 1 and 0 x 0 = 0
Now when it comes to coding, I found the following code for onTouchEvent:
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
switch(action) {
case MotionEvent.ACTION_DOWN : {
break;
}
case MotionEvent.ACTION_MOVE : {
break;
}
case MotionEvent.ACTION_POINTER_DOWN : {
break;
}
case MotionEvent.ACTION_POINTER_UP : {
break;
}
case MotionEvent.ACTION_UP : {
break;
}
}
return true;
}
Ok firstable, the part int action = event.getAction() & MotionEvent.ACTION_MASK; what is the value of action after the operation, and what does it means? why not just simply use action = event.getAction() what's the meaning.
second, I've never seen the use of {} to define a code block for a case: is this specific because we're using the bitwise and operator or this is something totally normal and I happen to just notice that you can use them?

The reason the event is masked is to remove unrelated bits from the event. Performing bitwise-and with ACTION_MASK isolates only those particular bits. This is how you combine and test status flags that are packed into an integer. If you did not mask it, then if any other bit is set on the event, you would not be able to easily test your actions for equality.
What this is actually doing is reserving a small number of bits for an action, like having a 3-bit integer (or whatever it actually is). The mask just sets the relevant bits, so that all other bits are thrown away (ie are unimportant).
As for the braces in case statements, that's fine. You can put braces just about anywhere - it creates a a block-scope level, where any new variables you create inside that block will only exist in the block. In case statements this is quite normal, and prevents a variable in one case from "falling through" to subsequent cases. For example:
switch(foo)
{
case 0:
int i = 42;
// do something with i
break;
case 1:
// The variable i is still in scope here, which is often not
// intentional (but can sometimes be useful)
}
To stop i from falling through:
switch(foo)
{
case 0:
{
int i = 42;
// do something with i
}
break;
case 1:
// The variable i defined above is not available here.
}
In your case, the braces are superfluous, but are probably there because the person who wrote the code has adopted this practice into their coding style. Most likely they've been burned by an unwanted side-effect before, or their compiler emits warnings about variable fall-through and they've decided to just use braces all the time. Personally, I think it's cleaner to only use them when necessary.

The event that comes back from event.getAction() is actually an integer. It contains more than just information about the type of action apparently. It probably contains flags that describe the action in more detail. And by passing all that detail in through an int, it saves the use of a class object to represent the action itself.
The mask is bitwise for the first byte in the integer. Only the first two bytes out of the eight. And for comparison purposes, you need to remove the upper parts of the integer before comparing it against the actions, which are themselves only using the bottom byte of an integer.
The upper parts of the event integer are still useful for other purposes when checking against them. So the mask is 0x000000ff representing that you only want information related to the action type at the bottom and the entire event takes up the rest of it with other useful information.

Related

Why is MotionEvent.ACTION_POINTER_UP not recorded consistently?

I thought pinch would always trigger MotionEvent.ACTION_POINTER_UP, but it happens only about 50% of the time (it varies a lot) for an app on at least two tested tablet devices. It appears to be random. I do not know how to pinch to make it happen consistently.
The code is very straightforward as the following overridden method of the activity in question:
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction())
{
...
case MotionEvent.ACTION_POINTER_UP:
Log.d("Debug", "ACTION_POINTER_UP triggered");
default:
break;
}
...
}
Could anyone shed some light on this?
You may change your code to use getActionMasked().
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked())
{
//...
case MotionEvent.ACTION_POINTER_UP:
Log.d("Debug", "ACTION_POINTER_UP triggered");
default:
break;
}
//...
}
MotionEven getAction() reports an integer which consists of both ACTION_whatever and
the pointer index left-shifted by ACTION_POINTER_INDEX_SHIFT (8) bits.
Return the kind of action being performed. Consider using getActionMasked() and getActionIndex() to retrieve the separate masked action and pointer index.
Returns
The action, such as ACTION_DOWN or the combination of ACTION_POINTER_DOWN with a shifted pointer index.
getAction() can be quite confusing to work with in multi-touch situations. If you want to get the kind of action (ACTION_DOWN, ACTION_POINTER_DOWN, and so on), which your case most likely is, you may use getActionMasked() instead of getAction().
getActionMasked() always returns ACTION_whatever, without the pointer index bits.
getAction() returns (getActionIndex() << 8 | ACTION_whatever).
(pointer indexes are very counter-intuitive, with Android trying to re-use the lowest indices available giving strange behavior if you use them directly, but that's another story, here better use getActionMasked() and not worry about indices). This is numerically equal to getActionMasked() only when the pointer has index=0, therefore you will see the "random" behavior: As you complete each pinch "naturally",
sometimes you may have released pointer 0 first, then pointer 1 last,
you get 2 events that getAction() returns ACTION_POINTER_UP followed by 1<<8 | ACTION_UP respectively, and hits the case ACTION_POINTER_UP label on the first event.
The other time you may have released pointer 1 first, then pointer 0 last,
you get 2 events that getAction() return 1<<8 | ACTION_POINTER_UP followed by ACTION_UP.
There is no case label for these, all get down to the default.
If you use getActionMasked(), you get ACTION_POINTER_UP followed by ACTION_UP, in both cases consistently.

How to refresh the screen in OpenGL after something is printed?

I have a couple of if-statements and if one of them is true it will print a character on the screen.
char d = 'a';
char c = 'b';
if(A == TRUE) //see comments below
{
Print(200,200,d);
}
if(B == TRUE)
{
Print(200,200,c);
}
void Print(int x, int y, char u)
{
glRasterPos2f(x,y);
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, u);
}
The problem is that if A is true, it will print 'a' on the screen correctly, but if afterwards B is true and A not anymore it will print 'b' on the screen while the character 'a' is still there. How can I solve this so that only one character is on the screen. Any help would be appreciated.
Big thanks to datenwolf. The most important thing is to put the glutPostRedisplay in the right place. I placed it at the end of my void Print(..) function. I just looked where I should place it and for me this works now (it was just a small adjustment).
OpenGL's design is built on the premise, that the while window is redrawn if anything needs a change. Normally all drawing operations should be done from only a central display function. Changes that need to be reflected in what's visible on the screen should be dealt with by preparing the list of things to be drawn and then issue a full redraw event.
Update
Actually you have a completely different problem
In the statement if(A = TRUE) two things are happening:
A gets assigned the value TRUE
the result of that assignment (which is TRUE) is tested for truth, which it is and hence will always pass.
The same goes for if(B = TRUE).
The right operator to use is == (two equal signs in a row). With most compilers you can enable a warning and turn that into an error, that assignments are not allowed in a branching statement. A stylistic approach is to write tests for equality as
if( TRUE == A )
which avoids accidents like yours. However in your case you can simply write
if( A )
without any comparison operators at all. And I strongly suggest you do that.

Assign ressource dynamically vs. big switch case

I have a question regarding performance and best approach for my Android code.
What I need to do is fairly simple, I want to dynamically assign a text value to a string ressource, depending on a int parameter:
For now I am using a big switch case
int messagesCategory;
if(extras !=null) {
messagesCategory = extras.getInt("category");
}
TextView titleText;
titleText = (TextView) findViewById(R.id.headerTitle);
switch (messagesCategory) {
case 1: titleText.setText(R.string.TitleMessageList1); break;
case 2: titleText.setText(R.string.TitleMessageList2); break;
case 3: titleText.setText(R.string.TitleMessageList3); break;
case 4: titleText.setText(R.string.TitleMessageList4); break;
case ...: titleText.setText(R.string.TitleMessageList...); break;
case n: titleText.setText(R.string.TitleMessageListn); break;
default: titleText.setText("a default title"); break;
}
Let's say I have 30 lines in this switch...
It works but for many cases, it looks there is a better way to achieve this.
Unfortunately it does not look possible to assign something dynamic to R.string..
So my first question is: 1) performance wise, in this case, is it a problem to use a big switch for 30 cases or so?
2) what should be the best approach?
Thanks and have a good day
Simple,
int[] stringIds = {R.string.TitleMessageList1, R.string.TitleMessageList2,...};
int messagesCategory;
TextView titleText = (TextView) findViewById(R.id.headerTitle);
if(extras !=null) {
messagesCategory = extras.getInt("category");
if(messagesCategory <= n)
titleText.setText(stringIds[messagesCategory]);
else titleText.setText("a default title");
}
Now, there is no switch-case and comparison,, Basic Java and Android fundamentals make it to easy and short..
As R.string.XXX is an int value generated in R.java file you have to make a just int array of that values and just get value using your int messagesCategory. And directly set it to TextView..
You can also do this:
Field f = R.id.class.getField("TitleMessageList" + String.valueOf(messagesCategory));
int val = f.getInt(null);
titleText.setText(val);
It is fast without need to load all ids in the memory.
Enjoy!
switch case is the equivalent of GOTO in your code, and there is nothing to worry about with performance.
your code is fine, may not be nice but it works and it's efficient.
I don't think 30 case statements don't hurt much except you execute them in a loop, iterating over an array, and such.
Why don't you directly use the integers which R.string gives you? Is the mapping really necessary? You could pass the R.string identifiers around. Or else, you could have a lookup in an array if you're really worried about performance.

Android multitouch and getActionMasked()

I have a some small questions to do with the masking of touch events. I have read many things on here and elsewhere but am still a little confused with parts.
1) Is event.getActionMasked() same as event.getAction() & MotionEvent.ACTION_MASK (they appear to be on Samsung S2 and HTC Desire)
2) Will the two above commands give all the information and more than that event.getAction() alone will, or is it different.
3) I have written a peice of code which simple says where is being touch and with which pointerId, or if the pointer is not in use (only written for two touches at the moment). It seems to work correctly on the devices mention above, however I know how some devices can act very differently if not done absolutely correct. I am therefore wondering if the following is correct and will behave on all devices.
boolean pointer0down=false, pointer1down=false;
String st="", str0 ="", str1 ="";
public boolean onTouchEvent( MotionEvent event )
{
if (event.getActionMasked()==MotionEvent.ACTION_UP
||event.getActionMasked()==MotionEvent.ACTION_POINTER_UP
||event.getActionMasked()==MotionEvent.ACTION_CANCEL)
{
if (event.getPointerId((event.getActionIndex()& MotionEvent.ACTION_MASK))==0)
pointer0down=false;
if (event.getPointerId((event.getActionIndex()& MotionEvent.ACTION_MASK))==1)
pointer1down=false;
}
if (event.getActionMasked()==MotionEvent.ACTION_DOWN
||event.getActionMasked()==MotionEvent.ACTION_POINTER_DOWN)
{
if (event.getPointerId((event.getActionIndex()& MotionEvent.ACTION_MASK))==0)
pointer0down=true;
if (event.getPointerId((event.getActionIndex()& MotionEvent.ACTION_MASK))==1)
pointer1down=true;
}
if (pointer0down)
str0="\tx: " + event.getX(0) + "\ty: "+event.getY(0);
else
str0="\tNot down";
if (pointer1down )
str1="\tx: " + event.getX(1) + "\ty: "+event.getY(1);
else
str1="\tNot down";
st="pointer0:"+str0+"\npointer1:"+str1;
return true;
}
Some background -
The integer returned from getAction is a packed integer that encodes both the action code (e.g ACTION_DOWN) and pointer index (e.g which finger).
For single touch, since there is only one finger involved there is no need to store the pointer index so the value is just the action code. Hence its safe to do something like getAction() == ACTION_DOWN
For multi touch, this comparison is incorrect b/c you have the extra pointer index in the packaged integer. You can extract the action code by doing getAction() & ACTION_MASK and extract the pointer index by doing getAction() & ACTION_POINTER_INDEX_MASK
Now to your question -
1: Yes. think of getActionMasked as a helper method that extract the action code bits. To extract the pointer index you have the equivalent getActionIndex helper method. Both these methods will work for single or multi touch hence they are the "safest".
2: As explained above, getAction also encodes pointer index for multitouch
3: there is a bug in your code. event.getPointerId((event.getActionIndex() & MotionEvent.ACTION_MASK)) is technically incorrect. Instead you should be doing event.getPointerId(event.getActionIndex()). You are getting very lucky with the incorrect logical and operator on getActionIndex which turns out to be 2 bytes and the mask is itself 2 bytes (0xff) :)

Android Motion Event Hold Down Button

I have a seemingly simple question that I need help with. I have a button. I want it so when I click on the button quickly it adds one to a total. I also want it to be so that when I hold down this same button for about 2 seconds, it removes one from the total. The only part I am having trouble with is the motion event part. I have been experimenting with ACTION_UP and ACTION_DOWN with no luck. Is there an easy way to do this?
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
total ++;
return true;
}
case MotionEvent.ACTION_UP:
{
if(total >0){
total--;
}
return true;
}
}
Thanks for the help!
Why not use the Button's setOnClickListener and setOnLongClickListener?
The only limitation with this approach is that you cannot set the the timeout value, which is somewhat over 1,5 seconds, if I remember correctly.
If you're persistent about the two seconds (or some other value), then I suppose you could use an onTouchListener and keep track of the pressed time yourself. In that case, the MotionEvent's getDownTime might be of interest to you.

Categories

Resources