pointerIndex out of range Android multitouch
Asked Answered
A

7

45

I have a touch event exception that is causing my game to crash on tablets (or more specifically, honeycomb)... My game works fine on my phone and I haven't heard of this happening to anyone that isn't running Android 3.0 or higher. Here is the relevant log info...

E/AndroidRuntime(26487): java.lang.IllegalArgumentException: pointerIndex out of range
E/AndroidRuntime(26487):    at android.view.MotionEvent.nativeGetAxisValue(Native Method)
E/AndroidRuntime(26487):    at android.view.MotionEvent.getX(MotionEvent.java:1549)
E/AndroidRuntime(26487):    at kieran.android.asteroids.GameUI.onTouchEvent(GameUI.java:665)
E/AndroidRuntime(26487):    at android.view.View.dispatchTouchEvent(View.java:4616)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560)
E/AndroidRuntime(26487):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291)

... And here is the code that is calling it. Seems fine to me, but maybe there is a bug in honeycomb that hasn't been fixed yet? The line number 665 from the log above corresponds to the float x = event.getX(id); line. It must have something to do with the way I am getting the which variable maybe? But it works fine on the phones/2.3 and lower...

int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;

if(actionCode == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_UP) {
    int which = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
    int id = event.getPointerId(which);
    float x = event.getX(id);
    float y = event.getY(id);

Any help/ideas would be greatly appreciated as I am trying to make my game available to tablet users as well. Thanks.

Alleman answered 2/8, 2011 at 22:7 Comment(1)
Yes, I have exactly the same problem on HoneyComb only with my mini piano. On phones it's just behaving normally.Pasley
O
56

My problem was that it was actually calling event.getX(1) when there wasn't actually two ids. So I made sure that there were two ids with event.getPointerCount() >= 2 and it now works. Maybe you'll have the same luck!

Olid answered 7/9, 2011 at 19:6 Comment(3)
You are awesome! That is exactly my problem. I am still unsure as to why I don't have this problem on phones but for now this has fixed my force close problem. Thanks a lot!Alleman
this is the best solution! Using the Pointer Index calculations that are suggested by David and Chris will prevent zoom-in and zoom-out on the Samsung Note 2Merissameristem
no luck for me, I applied ev.getPointerCount() > 10 in onInterceptTouchEvent but it still crashedSixgun
P
19

For those who are still looking for answers please note that this may happen also when you are using any ViewPager with some Zooming or Scaling features on image etc inside it. Then there is a possibility you can get this Exception as well.

Solution:

Extend the existing ViewPager and override these methods with try catch.

@Override
public boolean onTouchEvent(MotionEvent ev) {
    try {
        return super.onTouchEvent(ev);
    } catch (IllegalArgumentException ex) {
        ex.printStackTrace();
    }
    return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    try {
        return super.onInterceptTouchEvent(ev);
    } catch (IllegalArgumentException ex) {
        ex.printStackTrace();
    }
    return false;
}
Preponderate answered 31/12, 2019 at 11:23 Comment(1)
You are awesome! That is exactly my problem.Dight
G
10

Your missing a few things, you need to apply the mask to the pointer otherwise as you are not technically accessing the ID of the finger you think you are

int action = event.getAction() & MotionEvent.ACTION_MASK;     
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
int pointerId = event.getPointerId(pointerIndex);
Gaby answered 3/8, 2011 at 0:18 Comment(6)
Hmmmm... I understand what you mean. Though after changing it I still get the same error. The error is coming from the getX() method. Which I logged the pointer index before passing to that function and it is usually just a positive 1, 2, or 3 etc..., depending on which pointer it was. Any other ideas?Alleman
are you using event.getX(pointerIndex) now? getY is probably doing the same thing its just not getting that far in the code. Does this crash when you touch the screen? If so how many touches does it take to break itGaby
Also where is this code being called? Is it just within onTouch?Gaby
Yes I am using event.getX(pointerIndex) now, and yea I'm positive getY() would do the same but it's obviously crashing just before that. It takes 2 touches to break it, I put one pointer down, then put a second down, then bring the first up and it crashes. And yes just within the onTouchEvent(). I don't quite understand it because it works on my phone but not my tablet.Alleman
Run in debug and see what values pointerIndex and pointerID return just before the crashGaby
Ok so I logged the values just before the crash and it is returning pointerIndex=0 and pointerId=1... the code looks exactly the same as what you posted above.Alleman
F
4

I'm also having this error but none of the solutions before the date of my post work. The only temporary pseudo-fix which works for me is to use a try-catch against IllegalArgumentException.

According to Android Issue 18990, it is related to ScaleGestureDetector and a fix has been committed few days ago.

Fu answered 21/10, 2012 at 17:34 Comment(2)
Perfect solutionMurdock
I also use ScaleGestureDetector. But even if this bug is fixed, how could we back-port this solution to our builds?Nubia
F
2

The original posting is using the pointer id when the getX and getY use the pointer index.

It appears to work when you use the ID for a single touch because the id and the index are both 0. It will mess up if you use a multi-touch because the indices can change.

Example:

  • Touch 1 Down.
    Touch 1 State Index=0. ID=0

  • Touch 2 Down.
    Touch 1 State Index=0. ID=0
    Touch 2 State Index=1. ID=1

  • Touch 1 Release.
    Touch 2 State Index=0. ID=1

Try the following code:

int action = event.getAction();     
int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                   >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;       
float x = event.getX(pointerIndex);
float y = event.getY(pointerIndex);
Fauman answered 21/1, 2013 at 3:54 Comment(1)
Thanks to this answer, I found the fact that there are pointerIndex and pointerId and the arguments of getX and getY are the former. That was what I had overlooked for a long time.Lyallpur
G
1

Just change your getPointerId() to findPointerIndex(). Maybe change geAction() to getActionMasked().

Hope it helps!

Georgiana answered 4/9, 2011 at 21:22 Comment(2)
Damnnn no go on that either... I had high hopes for this to work. It's hard to believe that I haven't found a solution to this problem yet, I can't be the only one that has had this problem. I've tried so many things...Alleman
iam using findPointerIndex() getActionMasked() but still getting crash in multitouch.Polite
R
0

This worked for me :

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    try {
        return super.dispatchTouchEvent(ev);
    } catch (IllegalArgumentException ex) {
        ex.printStackTrace();
    }
    return false;
}
Resistance answered 5/10, 2022 at 9:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.