0
ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(getActivity(), new ScaleListener());
relativeLayoutCell.setOnTouchListener((v, event) -> {
   scaleGestureDetector.onTouchEvent(event);
}



private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float fScaleCurrent = detector.getScaleFactor();
            ...
   
            return true;
        }
    }

scaleGestureDetector.onTouchEvent(event) occasionally throws the following exception:

Class: java.lang.RuntimeException
 Stack trace: java.lang.RuntimeException: MotionEvent { action=ACTION_UP, actionButton=0, id[0]=1, x[0]=627.41907, y[0]=331.80536, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=37639130, downTime=37638540, deviceId=3, source=0x1002, displayId=0, eventId=620448886 } recycled twice!
    at android.view.InputEvent.recycle(InputEvent.java:134)
    at android.view.MotionEvent.recycle(MotionEvent.java:2044)
    at android.view.GestureDetector.onTouchEvent(GestureDetector.java:767)
    at android.view.ScaleGestureDetector.onTouchEvent(ScaleGestureDetector.java:240)

There is no code to recycle anything. Could anyone offer a hint about the possible cause?

Update 2023-04-29

The following new code still throws the exception

ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(getActivity(), new ScaleListener());
relativeLayoutCell.setOnTouchListener((v, event) -> {
   MotionEvent eventCopy = MotionEvent.obtain(event);
   executorService.execute(()->{
      executorServiceSingleThread.submit(()->{
         scaleGestureDetector.onTouchEvent(eventCopy);
      });
   })
   //eventCopy is also consumed by other code in this block
   
}

scaleGestureDetector.onTouchEvent(eventCopy) in the above code still throws the exception despite eventCopy is used.

Update 2023-05-03

The following new code still throws the exception

ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(getActivity(), new ScaleListener());
relativeLayoutCell.setOnTouchListener((v, event) -> {
   MotionEvent eventCopyA = MotionEvent.obtain(event);
   MotionEvent eventCopyB = MotionEvent.obtain(event);
   executorService.execute(()->{
      executorServiceSingleThread.submit(()->{
         scaleGestureDetector.onTouchEvent(eventCopyA);
      });
   })
   //eventCopyB is also consumed by other code in this block
   
}

scaleGestureDetector.onTouchEvent(eventCopyA) in the above code still throws the exception despite eventCopyA is used only once and by that statement.

Update 2023-05-26

More than 90% of these exceptions are thrown by Android 13 devices. The rest is from Android 12. The app has troubles with MotionEvent on Android 13 devices.

Hong
  • 17,643
  • 21
  • 81
  • 142

0 Answers0