Open paulVulog opened 2 years ago
@paulVulog thank you for reporting, I will transfer this ticket to the appropriate repo.
@ZiZasaurus any status on this ? It is really impacting. Where did you transfer this issue to ?
Hi, similiar backtrace here https://github.com/appxmod/diodict-decompiled/commit/719900901b1a2acabace2e068a1ddb63778b5aa7
If I filter out ACTION_POINTER_DOWN
,the native crash will become the “pointerIndex out of range” Exception:
if (actionMasked!=MotionEvent.ACTION_POINTER_DOWN) {
try {
boolean flingEvent = this.flingDetector.onTouchEvent(event);
if (flingEvent) {
// this.flingDetector = new GestureDetector(getContext(), this);
return flingEvent;
}
} catch (Exception e) {
e.printStackTrace();
}
}
I resolved this issue by create new Flutter Engine with custom MyPlatformViewController extend PlatformViewController https://github.com/flutter/engine/pull/34182/commits/991471b66d1dced23b0962b6440314ae7c4a787d
MyPlatformViewController:
class MyPlatformViewsController : PlatformViewsController() {
override fun toMotionEvent(
density: Float,
touch: PlatformViewsChannel.PlatformViewTouch?,
usingVirtualDiplays: Boolean
): MotionEvent {
val motionEventId = MotionEventId.from(touch!!.motionEventId)
val trackedEvent = MotionEventTracker.getInstance().pop(motionEventId)
// Pointer coordinates in the tracked events are global to FlutterView
// framework converts them to be local to a widget, given that
// motion events operate on local coords, we need to replace these in the tracked
// event with their local counterparts.
// Pointer coordinates in the tracked events are global to FlutterView
// framework converts them to be local to a widget, given that
// motion events operate on local coords, we need to replace these in the tracked
// event with their local counterparts.
val pointerProperties = parsePointerPropertiesList(
touch!!.rawPointerPropertiesList
).toTypedArray()
val pointerCoords = parsePointerCoordsList(
touch!!.rawPointerCoords, density
)
.toTypedArray()
return if (!usingVirtualDiplays && trackedEvent != null) {
MotionEvent.obtain(
trackedEvent.downTime,
trackedEvent.eventTime,
touch!!.action,
touch!!.pointerCount,
pointerProperties,
pointerCoords,
trackedEvent.metaState,
trackedEvent.buttonState,
trackedEvent.xPrecision,
trackedEvent.yPrecision,
trackedEvent.deviceId,
trackedEvent.edgeFlags,
trackedEvent.source,
trackedEvent.flags
)
} else MotionEvent.obtain(
touch!!.downTime.toLong(),
touch!!.eventTime.toLong(),
touch!!.action,
touch!!.pointerCount,
pointerProperties,
pointerCoords,
touch!!.metaState,
touch!!.buttonState,
touch!!.xPrecision,
touch!!.yPrecision,
touch!!.deviceId,
touch!!.edgeFlags,
touch!!.source,
touch!!.flags
)
}
private fun parsePointerPropertiesList(rawPropertiesList: Any): List<PointerProperties> {
val rawProperties = rawPropertiesList as List<Any>
val pointerProperties: MutableList<PointerProperties> = java.util.ArrayList()
for (o in rawProperties) {
pointerProperties.add(parsePointerProperties(o))
}
return pointerProperties
}
private fun parsePointerProperties(rawProperties: Any): PointerProperties {
val propertiesList = rawProperties as List<Any>
val properties = PointerProperties()
properties.id = propertiesList[0] as Int
properties.toolType = propertiesList[1] as Int
return properties
}
private fun parsePointerCoordsList(rawCoordsList: Any, density: Float): List<PointerCoords> {
val rawCoords = rawCoordsList as List<Any>
val pointerCoords: MutableList<PointerCoords> = ArrayList()
for (o in rawCoords) {
pointerCoords.add(parsePointerCoords(o, density))
}
return pointerCoords
}
private fun parsePointerCoords(rawCoords: Any, density: Float): PointerCoords {
val coordsList = rawCoords as List<Any>
val coords = PointerCoords()
coords.orientation = (coordsList[0] as Double).toFloat()
coords.pressure = (coordsList[1] as Double).toFloat()
coords.size = (coordsList[2] as Double).toFloat()
coords.toolMajor = (coordsList[3] as Double * density).toFloat()
coords.toolMinor = (coordsList[4] as Double * density).toFloat()
coords.touchMajor = (coordsList[5] as Double * density).toFloat()
coords.touchMinor = (coordsList[6] as Double * density).toFloat()
coords.x = (coordsList[7] as Double * density).toFloat()
coords.y = (coordsList[8] as Double * density).toFloat()
return coords
}
}
In MainActivity (your main flutter activity):
override fun provideFlutterEngine(context: Context): FlutterEngine? {
return FlutterEngine(
context,
null,
FlutterJNI(),
MyCustomFlutterEngine(),
Companion.flutterShellArgs.toArray(),
false
)
}
Environment
Observed behavior and steps to reproduce
When running an app with MapboxMap.useHybridComposition = true; and doing some multitouch on the map, you can easily get some app crashes.
here are the produced logs :
Way to reproduce using the Mapbox Gl sample app:
This will simply add a widget on top of the map to reproduce the crash.
One digit on the map The Other One on the green widget Tap both at the same time.
You will get a crash.
It only crash if you tap a widget (flutter) stacked on top of the map (nativ view because of .useHybridComposition = true)
Expected behavior
We should not get any crash. Minimum requirement is to silently catch the exception. (this is what google maps seems to do - see below)
Notes / preliminary analysis
I have tested the same behavior on the GoogleMap sample app : https://github.com/flutter/plugins/tree/main/packages/google_maps_flutter/google_maps_flutter
I am able to reproduce the same kind of issue, Except that the google map do not Crash. There is only some flutter Error log :
Additional links and references
The issue is tracked in this repository - forwarded to the main Android Mapbox repository here: https://github.com/flutter-mapbox-gl/maps/issues/1077