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.