From 2f08c7371b33d03a10deb7c428a655f516f90221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Tue, 13 Oct 2026 04:02:07 +0200 Subject: [PATCH] fix(android): support bundled images in ImageSource release builds In release builds require()'d images reach ImageSource as drawable resource names instead of Metro URLs, and makeSource threw. Decode the resource into a bitmap and push it with ImageSource.updateImage. Fixes #3671 --- .../styles/sources/RNMBXImageSource.kt | 47 ++++++++++++------- .../components/styles/sources/RNMBXSource.kt | 2 +- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXImageSource.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXImageSource.kt index 0232027469..141ef1f37b 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXImageSource.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXImageSource.kt @@ -1,31 +1,40 @@ package com.rnmapbox.rnmbx.components.styles.sources import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory import android.net.Uri import android.util.Log import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper +import com.mapbox.maps.Style import com.mapbox.maps.extension.style.sources.generated.ImageSource +import com.mapbox.maps.extension.style.sources.updateImage +import com.rnmapbox.rnmbx.components.mapview.RNMBXMapView import com.rnmapbox.rnmbx.utils.LatLngQuad +import com.rnmapbox.rnmbx.utils.Logger import java.net.URL class RNMBXImageSource(context: Context?) : RNMBXSource(context) { private var mURL: URL? = null - private var mResourceId = 0 + // Release builds bundle require()'d images as drawable resources rather than serving them from a URL. + private var mBitmap: Bitmap? = null private var mCoordQuad: LatLngQuad? = null override fun hasNoDataSoRefersToExisting(): Boolean { - return mURL == null + return mURL == null && mBitmap == null } override fun makeSource(): ImageSource? { - if (mURL == null) { - throw RuntimeException("ImageSource without URL not supported in v10, resourceId is not supported") - } - val id = iD; - if (id == null) { - throw RuntimeException("ImageSource without ID not supported in v10") - } - return ImageSource.Builder(id).coordinates(mCoordQuad!!.coordinates).url(mURL.toString()).build() + val id = iD ?: throw RuntimeException("ImageSource without ID is not supported") + val builder = ImageSource.Builder(id).coordinates(mCoordQuad!!.coordinates) + mURL?.let { builder.url(it.toString()) } + return builder.build() + } + + override fun addToMap(existings: Boolean, style: Style, mapView: RNMBXMapView) { + super.addToMap(existings, style, mapView) + // updateImage only works once the source is part of the style. + mBitmap?.let { mSource?.updateImage(it) } } override fun onPress(feature: OnPressEvent?) { @@ -36,19 +45,23 @@ class RNMBXImageSource(context: Context?) : RNMBXSource(context) { try { val uri = Uri.parse(url) if (uri.scheme == null) { - mResourceId = + val resourceId = ResourceDrawableIdHelper.getInstance().getResourceDrawableId(this.context, url) - if (mSource != null) { - throw RuntimeException("ImageSource Resource id not supported in v10") + val bitmap = BitmapFactory.decodeResource(context.resources, resourceId) + if (bitmap == null) { + Logger.w(LOG_TAG, "Could not decode image resource: $url") + return } + mURL = null + mBitmap = bitmap + mSource?.updateImage(bitmap) } else { + mBitmap = null mURL = URL(url) - if (mSource != null) { - mSource!!.url(mURL.toString()) - } + mSource?.url(mURL.toString()) } } catch (e: Exception) { - Log.w(LOG_TAG, e.localizedMessage) + Logger.w(LOG_TAG, "Failed to set ImageSource url: $url", e) } } diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXSource.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXSource.kt index 3dec5bbe5a..4df1f797f7 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXSource.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXSource.kt @@ -104,7 +104,7 @@ abstract class RNMBXSource(context: Context?) : AbstractMapFeature( } else mTouchHitbox } - fun addToMap(existings: Boolean, style: Style, mapView: RNMBXMapView) { + open fun addToMap(existings: Boolean, style: Style, mapView: RNMBXMapView) { mSource = null val existingSource = getSourceAs(style, iD) if (existingSource != null) {