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.

DRiFTy
  • 11,269
  • 11
  • 61
  • 77
  • Yes, I have exactly the same problem on HoneyComb only with my mini piano. On phones it's just behaving normally. – Peterdk Oct 08 '11 at 11:05

7 Answers7

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!

Millec8
  • 887
  • 8
  • 17
  • 1
    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! – DRiFTy Sep 07 '11 at 21:07
  • 1
    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 2 – Someone Somewhere May 22 '13 at 22:34
  • no luck for me, I applied ev.getPointerCount() > 10 in onInterceptTouchEvent but it still crashed – Steve Luck Apr 23 '16 at 03:48
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;
}
vikas kumar
  • 10,447
  • 2
  • 46
  • 52
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);
Chris
  • 1,766
  • 1
  • 21
  • 36
  • 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? – DRiFTy Aug 03 '11 at 00:36
  • 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 it – Chris Aug 03 '11 at 00:50
  • Also where is this code being called? Is it just within onTouch? – Chris Aug 03 '11 at 00:53
  • 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. – DRiFTy Aug 03 '11 at 01:23
  • Run in debug and see what values pointerIndex and pointerID return just before the crash – Chris Aug 03 '11 at 07:57
  • 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. – DRiFTy Aug 03 '11 at 17:00
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.

vikas kumar
  • 10,447
  • 2
  • 46
  • 52
Aladin Q
  • 550
  • 5
  • 12
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);
hata
  • 11,633
  • 6
  • 46
  • 69
  • 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. – hata Dec 21 '21 at 13:31
1

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

Hope it helps!

fireshadow52
  • 6,298
  • 2
  • 30
  • 46
  • 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... – DRiFTy Sep 06 '11 at 01:12
  • iam using findPointerIndex() getActionMasked() but still getting crash in multitouch. – RAHULRSANNIDHI Apr 02 '14 at 12:44
0

This worked for me :

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