I managed to implement multitouch feature for the project I'm currently porting to Android at our Studio. I followed the exquisite example written by Tim Bray on the Android Dev Blogspot (http:// android-developers.blogspot.com/2010/06/making-sense-of- multitouch.html) and adapted the code to our needs (there was no need to add the Gesture Detector section and had to call native engine methods). Everything worked marvelously once I booted the application. Then I went back to the section I just coded in order to make sure the project would be compatible with API level 6. I found myself a little bit puzzled once I found out that the technique used to get the pointer index through the action flags (MotionEvent.ACTION_POINTER_INDEX_MASK >> MotionEvent.ACTION_POINTER_INDEX_SHIFT) hadn't been implemented until Froyo.
What troubles me is that I verify Multitouch features through: aPackageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH); which was implemented in API 7, but I am unable to correctly track the multiple pointer IDs unless the application runs on API8++. There was even another post relating to reflection and backward compatibility using the very same touchexample project (http://android- developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it- too.html) in which those methods were kept inside the Eclair specific code: private static class EclairDetector extends CupcakeDetector { private static final int INVALID_POINTER_ID = -1; private int mActivePointerId = INVALID_POINTER_ID; private int mActivePointerIndex = 0; @Override float getActiveX(MotionEvent ev) { return ev.getX(mActivePointerIndex); } @Override float getActiveY(MotionEvent ev) { return ev.getY(mActivePointerIndex); } @Override public boolean onTouchEvent(MotionEvent ev) { final int action = ev.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mActivePointerId = ev.getPointerId(0); break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: mActivePointerId = INVALID_POINTER_ID; break; case MotionEvent.ACTION_POINTER_UP: final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final int pointerId = ev.getPointerId(pointerIndex); if (pointerId == mActivePointerId) { // This was our active pointer going up. Choose a new // active pointer and adjust accordingly. final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mActivePointerId = ev.getPointerId(newPointerIndex); mLastTouchX = ev.getX(newPointerIndex); mLastTouchY = ev.getY(newPointerIndex); } break; } mActivePointerIndex = ev.findPointerIndex(mActivePointerId); return super.onTouchEvent(ev); } } I am now wondering if the Index Mask methods will be compatible running on Eclair or do I have to find a workaround (I have no clue how I could track the pointers without these) or even if I would need to raise the bar on multitouch support so that only users using Froyo or higher will be getting the goods? Thank you! Any help will be greatly appreciated! Below is my current code snippet: @Override public boolean onTouchEvent(MotionEvent event) { boolean result = false; final int action = event.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { if(mCanMultitouch) { // Save the ID of this pointer for later ACTION_POINTER_UP comparison mPrimaryPointerId = event.getPointerId(0); /*NativeTouchDownFunction*/(mPrimaryPointerId, (int)event.getY(), (int)event.getX()); } else { /*NativeTouchDownFunction*/(0, (int)event.getRawY(), (int)event.getRawX()); } result = true; break; } case MotionEvent.ACTION_MOVE: { if(mCanMultitouch) { // Find the index of the active pointer and fetch its position final int pointerIndex = event.findPointerIndex(mPrimaryPointerId); /*NativeTouchMoveFunction*/(mPrimaryPointerId, (int)event.getY(pointerIndex), (int)event.getX(pointerIndex)); } else { /*NativeTouchMoveFunction*/(0, (int)event.getRawY(), (int)event.getRawX()); } result = true; break; } case MotionEvent.ACTION_UP: { if(mCanMultitouch) { // Find the index of the active pointer and fetch its position final int pointerIndex = event.findPointerIndex(mPrimaryPointerId); /*NativeTouchUpFunction*/(mPrimaryPointerId, (int)event.getY(pointerIndex), (int)event.getX(pointerIndex)); mPrimaryPointerId = INVALID_POINTER_ID; } else { /*NativeTouchUpFunction*/(0, (int)event.getRawY(), (int)event.getRawX()); } result = true; break; } case MotionEvent.ACTION_CANCEL: { if(mCanMultitouch) { // Find the index of the active pointer and fetch its position final int pointerIndex = event.findPointerIndex(mPrimaryPointerId); /*NativeTouchUpFunction*/(mPrimaryPointerId, (int)event.getY(pointerIndex), (int)event.getX(pointerIndex)); mPrimaryPointerId = INVALID_POINTER_ID; } else { /*NativeTouchUpFunction*/(0, (int)event.getRawY(), (int)event.getRawX()); } result = true; break; } // Event only called when a pointer is already present and the view catches an additional pointer. case MotionEvent.ACTION_POINTER_DOWN: { // Extract the index of the pointer that entered the touch sensor final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final int pointerId = event.getPointerId(pointerIndex); /*NativeTouchDownFunction*/(pointerId, (int)event.getY(pointerId), (int)event.getX(pointerId)); result = true; break; } // Event only called when multiple pointer are detected and only one of them is released while the others remain on-screen. case MotionEvent.ACTION_POINTER_UP: { // Extract the index of the pointer that left the touch sensor final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final int pointerId = event.getPointerId(pointerIndex); if (pointerId == mPrimaryPointerId) { // This was our active pointer going up. /*NativeTouchUpFunction*/(mPrimaryPointerId, (int)event.getY(pointerId), (int)event.getX(pointerId)); //Choose a new active pointer and adjust accordingly. final int newPointerIndex = pointerIndex == 0 ? 1 : 0; mPrimaryPointerId = event.getPointerId(newPointerIndex); } else { /*NativeTouchUpFunction*/(pointerId, (int)event.getY(pointerId), (int)event.getX(pointerId)); } result = true; break; } } return result; } -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en

