[Android] - Query SymbolLayer using `queryRenderedFeaturesInRect` just received an empty `FeatureCollection`
Describe the bug
I was trying to find drop-pins wrapped in a certain bounding box, in specified layerIds and null filter using MapView method queryRenderedFeaturesInRect. Each drop-pin is implemented with the combination of ShapeSource & SymbolLayer.
It worked fine on iOS, even iOS 14 but on Android, it sucked. The result only contains an empty array typed FeatureCollection.
However, method queryRenderedFeaturesInRect works with LineLayer both on Android and iOS.
To Reproduce
Below is the implementation for handling selecting a Marker which is obscured by MapboxGL.UserLocation
Example:
// Marker
import React from 'react';
import {
MapView,
ShapeSource,
SymbolLayer,
Camera,
} from '@react-native-mapbox-gl/maps';
import {
Platform,
NativeModules,
NativeEventEmitter,
} from 'react-native';
const Marker = ({ id, onPress, coordinate, properties = {} }) => (
<ShapeSource
onPress={onPress}
id={id}
shape={{
type: 'Feature',
properties,
geometry: {
type: 'Point',
coordinates: coordinate,
},
}}
>
<SymbolLayer
id={`${id}-symbol`}
style={{
iconImage: 'https://s1.imghub.io/uzvBS.png',
iconAnchor: 'bottom',
iconAllowOverlap: true,
}}
/>
</ShapeSource>
)
// MapView
// -- get current user location (iOS)
const MyLocationDataManagerEmmiter = new NativeEventEmitter(NativeModules.MyLocationDataManager)
const getLocationManager = () => new Promise((resolve) => {
const list = MyLocationDataManagerEmmiter.addListener(
'significantLocationChange',
(data) => {
const { longitude, latitude } = data.location.coords
resolve({
longitude,
latitude,
})
list.remove()
},
(err) => console.log('err: ', err),
)
})
// -- get current user location (Android)
let _userLocationAndroid = null;
const handleUserLocationChange = (e) => {
if (e && Platform.OS === 'android' ) {
_userLocationAndroid = e.coords
}
}
// -- get bounding box for point{x, y}
export const calcBoundingBox = (point, boxEdgeHalfSize) => {
const nX = Number(point.x);
const nY = Number(point.y);
const halfSize = Number(boxEdgeHalfSize);
return [
nY - halfSize, // top
nX + halfSize, // right
nY + halfSize, // bottom
nX - halfSize, // left
]
}
<MapboxGL.MapView
ref={(ref) => { _map = ref || _map }}
>
<MapboxGL.Camera
ref={(ref) => {
if (ref) {
_camera = ref
}
}}
zoomLevel={7}
minZoomLevel={0}
maxZoomLevel={18}
followZoomLevel={18}
/>
<MapboxGL.UserLocation
showsUserHeadingIndicator
onUpdate={handleUserLocationChange}
onPress={async () => {
let lng
let lat
if (Platform.OS === 'ios') {
const { longitude, latitude } = await getLocationManager()
lng = longitude
lat = latitude
} else {
if (!_userLocationAndroid) return
const { latitude, longitude } = _userLocationAndroid
lng = longitude
lat = latitude
}
if (Number.isNaN(lng) || Number.isNaN(lat)) {
return
}
const point = await _map.getPointInView([lng, lat])
console.log('_DEBUG_: point', point)
const bbox = calcBoundingBox({ x: point[0], y: point[1] }, 10)
console.log('_DEBUG_: bbox', bbox)
const layerIds = pins.map((pin) => `${pin.identifier}-symbol`)
console.log('_DEBUG_: layerIds', layerIds)
const featureCollections = await _map.queryRenderedFeaturesInRect(bbox, null, layerIds)
console.log('_DEBUG_: featureCollections', JSON.stringify(featureCollections, null, 2))
}}
/>
</MapboxGL.MapView>
Expected behavior
- The variable
featureCollectionsshould be exactly the same on both Android & iOS. - We can use
queryRenderedFeaturesInRectto find allSymbolLayerin provided bounding box.
Screenshots Result after clicking on UserLocation
iOS

Android

Versions (please complete the following information):
- Platform: [Android, iOS]
- Device: [Pixel 3a. iPhone 8]
- Emulator/ Simulator: [yes]
- OS: [Android 10]
- react-native-mapbox-gl Version [8.1.0-rc.5]
- React Native Version [0.63.3]
I'm getting a similar issue with queryRenderedFeaturesAtPoint on Android. Code works fine on iOS, but doesn't work on Android:
const onPress = useCallback(
async (feature: Feature) => {
if (__DEV__) {
console.log(feature);
}
if (feature.geometry.type !== 'Point') {
return;
}
const point = await mapRef.current?.getPointInView(
feature.geometry.coordinates,
);
console.log(point);
if (!point) {
return;
}
const featureQuery = await mapRef.current?.queryRenderedFeaturesAtPoint(
point,
);
console.log(featureQuery);
if (!featureQuery) {
return;
}
const tappedFeature = featureQuery.features.filter(
(f): f is Feature => f.id && f.properties?.name,
)[0];
if (tappedFeature) {
onSelectFeature?.(tappedFeature);
}
},
[onSelectFeature],
);
The logs are interesting, because if I do this exactly the same side-by-side in an iOS simulator and an Android emulator, these are the logs:
iOS: {"geometry": {"coordinates": [-0.1278433227608673, 51.50767608808047], "type": "Point"}, "properties": {"screenPointX": 199, "screenPointY": 431}, "type": "Feature"}
iOS: [198.9999997594527, 430.99999959695907]
iOS: {"features": [{"geometry": [Object], "id": 957821391, "properties": [Object], "type": "Feature"}], "type": "FeatureCollection"}
Android: {"geometry": {"coordinates": [-0.12793794265280667, 51.507698148552066], "type": "Point"}, "properties": {"screenPointX": 513.96240234375, "screenPointY": 850.95703125}, "type": "Feature"}
Android: [195.79519653320312, 324.1741027832031]
Android: {"features": [], "type": "FeatureCollection"}
On iOS getPointInView returns virtually the same numbers as the feature's screenPoint[X/Y] values, whereas on Android they are quite different. Could that be the issue?
Is #639 related to this? Also, getting this issue both on @react-native-mapbox-gl/[email protected] and rc.7
@jun-nguyen-goldenowl, can you please create an example within the /example app.
Preferably in the BugReportTemplate - make sure it runs afterwards.
Less time we spend setting up and debugging code samples is more time fixing the issue.
Thanks in advance 🙇
I can also confirm that the following snippet was necessary to make queryRenderedFeaturesAtPoint work with the result of getPointInView:
if (Platform.OS == 'android') {
point[0] *= PixelRatio.get();
point[1] *= PixelRatio.get();
}
Would it perhaps make sense to add a method queryRenderedFeaturesAtLocation that handles this internally? (In addition to fixing the underlying bug with getPointInView).
PRs appreciated :)
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Should we keep this open, even if nobody has had the time to fix it so far?
Should we keep this open, even if nobody has had the time to fix it so far?
Definitely, I'll at an appropriate label to the ticket. Maybe someone stumbles upon it and actually has time :D
@ferdicus could it be that fixing this bug is as simple as removing these two lines here? https://github.com/react-native-mapbox-gl/maps/blob/963a77b7ce716d1f5b8b64fd5a45c0fcf90aac61/android/rctmgl/src/main/java/com/mapbox/rctmgl/components/mapview/RCTMGLMapView.java#L922
I couldn't see any similar logic on the iOS counterpart here: https://github.com/react-native-mapbox-gl/maps/blob/9103f2db5a5600f6a29db1644b2a09e5979da58d/ios/RCTMGL/RCTMGLMapViewManager.m#L116
It could be that iOS works in device pixels, but it doesn't seem so.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
not stale
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Not stale
@ferdicus could it be that fixing this bug is as simple as removing these two lines here?
https://github.com/react-native-mapbox-gl/maps/blob/963a77b7ce716d1f5b8b64fd5a45c0fcf90aac61/android/rctmgl/src/main/java/com/mapbox/rctmgl/components/mapview/RCTMGLMapView.java#L922
I couldn't see any similar logic on the iOS counterpart here:
https://github.com/react-native-mapbox-gl/maps/blob/9103f2db5a5600f6a29db1644b2a09e5979da58d/ios/RCTMGL/RCTMGLMapViewManager.m#L116
It could be that iOS works in device pixels, but it doesn't seem so.
@savv , not sure - you can check the PR for the reasoning behind this addition: https://github.com/react-native-mapbox-gl/maps/pull/639
Maybe that'll give a hint
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Don't you dare stale bot
Any update or workaround for this? Still experiencing this issue with release 8.4.0 after migrating away from the deprecated library: https://github.com/nitaliano/react-native-mapbox-gl where it used to work consistently for both platforms.
getPointInView([ 4.4024642, 51.2194475 ]) on iOS returns [207, 447.999] while getPointInView() on Android returns [196.5, 391]. This prevents me from selecting the right geometry on Android. Tested on multiple Android and iOS devices.
(EDIT: Moved images in table for better viewing [ferdicus])
| iOS | Android |
|---|---|
![]() |
![]() |
Any update or workaround for this?
See here
https://github.com/react-native-mapbox-gl/maps/issues/1085#issuecomment-720729641
Any update or workaround for this?
See here
My bad totally missed that part, just tried it out and the fix is working like a charm! Thanks a lot @savv !
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Not stale
Pls try with current v10 releases and open a new issue if it's still happens there

