Skip to content

Commit 00c7f10

Browse files
authored
feat: improve error reporting
2 parents d36ca7f + 680a671 commit 00c7f10

16 files changed

Lines changed: 133 additions & 74 deletions

android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class GoogleMapsViewImpl(
6161
val locationHandler: LocationHandler,
6262
val playServiceHandler: PlayServicesHandler,
6363
val markerBuilder: MapMarkerBuilder,
64+
val mapErrorHandler: MapErrorHandler,
6465
) : FrameLayout(reactContext),
6566
GoogleMap.OnCameraMoveStartedListener,
6667
GoogleMap.OnCameraMoveListener,
@@ -135,7 +136,7 @@ class GoogleMapsViewImpl(
135136
val result = playServiceHandler.playServicesAvailability()
136137
val errorCode = result.toRNMapErrorCodeOrNull()
137138
if (errorCode != null) {
138-
onMapError?.invoke(errorCode)
139+
mapErrorHandler.report(errorCode, "play services unavailable")
139140
if (errorCode == RNMapErrorCode.PLAY_SERVICES_MISSING ||
140141
errorCode == RNMapErrorCode.PLAY_SERVICES_INVALID
141142
) {
@@ -396,7 +397,6 @@ class GoogleMapsViewImpl(
396397
)
397398
}
398399

399-
var onMapError: ((RNMapErrorCode) -> Unit)? = null
400400
var onMapReady: ((Boolean) -> Unit)? = null
401401
var onMapLoaded: ((RNRegion, RNCamera) -> Unit)? = null
402402
var onLocationUpdate: ((RNLocation) -> Unit)? = null
@@ -505,7 +505,7 @@ class GoogleMapsViewImpl(
505505
onUi {
506506
googleMap?.snapshot { bitmap ->
507507
bitmap
508-
?.encode(context, size, format, compressFormat, quality, resultIsFile)
508+
?.encode(context, size, format, compressFormat, quality, resultIsFile, mapErrorHandler)
509509
?.let(promise::resolve) ?: promise.resolve(null)
510510
}
511511
}
@@ -754,7 +754,7 @@ class GoogleMapsViewImpl(
754754
kmlLayersById[id] = layer
755755
layer.addLayerToMap()
756756
} catch (_: Exception) {
757-
mapsLog("kml layer parse failed: id=$id")
757+
mapErrorHandler.report(RNMapErrorCode.KML_LAYER_FAILED, "kml layer parse failed: id=$id")
758758
}
759759
}
760760

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.rngooglemapsplus
2+
3+
private const val MAPS_LOG_TAG = "react-native-google-maps-plus"
4+
5+
class MapErrorHandler {
6+
@Volatile
7+
var callback: ((RNMapErrorCode, String) -> Unit)? = null
8+
9+
fun report(
10+
code: RNMapErrorCode,
11+
msg: String,
12+
t: Throwable? = null,
13+
) {
14+
if (t != null) {
15+
android.util.Log.w(MAPS_LOG_TAG, msg, t)
16+
} else {
17+
android.util.Log.w(MAPS_LOG_TAG, msg)
18+
}
19+
20+
onUi {
21+
callback?.invoke(code, msg)
22+
}
23+
}
24+
}

android/src/main/java/com/rngooglemapsplus/MapHelper.kt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,3 @@ inline fun <T> onUiSync(crossinline block: () -> T): T {
2020
}
2121
return runBlocking { result.await() }
2222
}
23-
24-
private const val MAPS_LOG_TAG = "react-native-google-maps-plus"
25-
26-
fun mapsLog(msg: String) {
27-
android.util.Log.w(MAPS_LOG_TAG, msg)
28-
}
29-
30-
fun mapsLog(
31-
msg: String,
32-
t: Throwable,
33-
) {
34-
android.util.Log.w(MAPS_LOG_TAG, msg, t)
35-
}

android/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import kotlin.coroutines.cancellation.CancellationException
4343

4444
class MapMarkerBuilder(
4545
val context: ThemedReactContext,
46+
private val mapErrorHandler: MapErrorHandler,
4647
private val scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default),
4748
) {
4849
private val iconCache =
@@ -121,7 +122,7 @@ class MapMarkerBuilder(
121122
}
122123
}
123124
}.onFailure {
124-
mapsLog("external svg resolve failed")
125+
mapErrorHandler.report(RNMapErrorCode.MARKER_ICON_BUILD_FAILED, "external svg resolve failed")
125126
}.getOrNull()
126127
}
127128

@@ -145,7 +146,7 @@ class MapMarkerBuilder(
145146
try {
146147
return Typeface.createFromAsset(assetManager, path)
147148
} catch (_: Throwable) {
148-
mapsLog("font resolve failed: $path")
149+
mapErrorHandler.report(RNMapErrorCode.INVALID_ARGUMENT, "font resolve failed: $path")
149150
}
150151
}
151152

@@ -292,14 +293,14 @@ class MapMarkerBuilder(
292293
onReady(desc)
293294
}
294295
} catch (_: OutOfMemoryError) {
295-
mapsLog("markerId=${m.id} buildIconAsync out of memory")
296+
mapErrorHandler.report(RNMapErrorCode.MARKER_ICON_BUILD_FAILED, "markerId=${m.id} buildIconAsync out of memory")
296297
clearIconCache()
297298
withContext(Dispatchers.Main) {
298299
ensureActive()
299300
onReady(createFallbackDescriptor())
300301
}
301302
} catch (_: Throwable) {
302-
mapsLog("markerId=${m.id} buildIconAsync failed")
303+
mapErrorHandler.report(RNMapErrorCode.MARKER_ICON_BUILD_FAILED, "markerId=${m.id} buildIconAsync failed")
303304
withContext(Dispatchers.Main) {
304305
ensureActive()
305306
onReady(createFallbackDescriptor())
@@ -343,7 +344,7 @@ class MapMarkerBuilder(
343344
.toInt()
344345

345346
if (wPx <= 0 || hPx <= 0) {
346-
mapsLog("markerId=${markerTag.id} invalid svg size")
347+
mapErrorHandler.report(RNMapErrorCode.INVALID_ARGUMENT, "markerId=${markerTag.id} invalid svg size")
347348
return ImageView(context)
348349
}
349350

@@ -365,7 +366,7 @@ class MapMarkerBuilder(
365366
val drawable = PictureDrawable(svg.renderToPicture())
366367
svgView.setImageDrawable(drawable)
367368
} catch (_: Exception) {
368-
mapsLog("markerId=${markerTag.id} infoWindow: svg render failed")
369+
mapErrorHandler.report(RNMapErrorCode.MARKER_ICON_BUILD_FAILED, "markerId=${markerTag.id} infoWindow: svg render failed")
369370
return ImageView(context)
370371
}
371372

@@ -403,7 +404,7 @@ class MapMarkerBuilder(
403404
.toInt()
404405

405406
if (wPx <= 0 || hPx <= 0) {
406-
mapsLog("markerId=$markerId invalid svg size")
407+
mapErrorHandler.report(RNMapErrorCode.INVALID_ARGUMENT, "markerId=$markerId invalid svg size")
407408
return RenderBitmapResult(createFallbackBitmap(), true)
408409
}
409410

@@ -416,10 +417,10 @@ class MapMarkerBuilder(
416417
documentHeight = hPx.toFloat()
417418
}
418419
} catch (_: SVGParseException) {
419-
mapsLog("markerId=$markerId icon: svg parse failed")
420+
mapErrorHandler.report(RNMapErrorCode.INVALID_ARGUMENT, "markerId=$markerId icon: svg parse failed")
420421
return RenderBitmapResult(createFallbackBitmap(), true)
421422
} catch (_: IllegalArgumentException) {
422-
mapsLog("markerId=$markerId icon: svg invalid")
423+
mapErrorHandler.report(RNMapErrorCode.INVALID_ARGUMENT, "markerId=$markerId icon: svg invalid")
423424
return RenderBitmapResult(createFallbackBitmap(), true)
424425
}
425426

android/src/main/java/com/rngooglemapsplus/MapUrlTileOverlayBuilder.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import com.google.android.gms.maps.model.TileOverlayOptions
44
import com.google.android.gms.maps.model.UrlTileProvider
55
import java.net.URL
66

7-
class MapUrlTileOverlayBuilder {
7+
class MapUrlTileOverlayBuilder(
8+
private val mapErrorHandler: MapErrorHandler,
9+
) {
810
fun build(t: RNUrlTileOverlay): TileOverlayOptions {
911
val provider =
1012
object : UrlTileProvider(
@@ -25,7 +27,7 @@ class MapUrlTileOverlayBuilder {
2527
return try {
2628
URL(url)
2729
} catch (e: Exception) {
28-
mapsLog("tile url invalid: $url", e)
30+
mapErrorHandler.report(RNMapErrorCode.TILE_OVERLAY_FAILED, "tile url invalid: $url", e)
2931
null
3032
}
3133
}

android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,22 @@ import com.rngooglemapsplus.extensions.toSize
2424
class RNGoogleMapsPlusView(
2525
val context: ThemedReactContext,
2626
) : HybridRNGoogleMapsPlusViewSpec() {
27+
private val mapErrorHandler = MapErrorHandler()
28+
2729
private var currentCustomMapStyle: String? = null
2830
private var permissionHandler = PermissionHandler(context)
2931
private var locationHandler = LocationHandler(context)
3032
private var playServiceHandler = PlayServicesHandler(context)
3133

32-
private val markerBuilder = MapMarkerBuilder(context)
34+
private val markerBuilder = MapMarkerBuilder(context, mapErrorHandler)
3335
private val polylineBuilder = MapPolylineBuilder()
3436
private val polygonBuilder = MapPolygonBuilder()
3537
private val circleBuilder = MapCircleBuilder()
3638
private val heatmapBuilder = MapHeatmapBuilder()
37-
private val urlTileOverlayBuilder = MapUrlTileOverlayBuilder()
39+
private val urlTileOverlayBuilder = MapUrlTileOverlayBuilder(mapErrorHandler)
3840

3941
override val view =
40-
GoogleMapsViewImpl(context, locationHandler, playServiceHandler, markerBuilder)
42+
GoogleMapsViewImpl(context, locationHandler, playServiceHandler, markerBuilder, mapErrorHandler)
4143

4244
override var initialProps: RNInitialProps? = null
4345
set(value) {
@@ -303,9 +305,10 @@ class RNGoogleMapsPlusView(
303305
view.locationConfig = value
304306
}
305307

306-
override var onMapError: ((RNMapErrorCode) -> Unit)? = null
308+
override var onMapError: ((RNMapErrorCode, String) -> Unit)? = null
307309
set(cb) {
308-
view.onMapError = cb
310+
field = cb
311+
mapErrorHandler.callback = cb
309312
}
310313

311314
override var onMapReady: ((Boolean) -> Unit)? = null

android/src/main/java/com/rngooglemapsplus/extensions/BitmapExtension.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import android.graphics.Bitmap
55
import android.util.Base64
66
import android.util.Size
77
import androidx.core.graphics.scale
8-
import com.rngooglemapsplus.mapsLog
8+
import com.rngooglemapsplus.MapErrorHandler
9+
import com.rngooglemapsplus.RNMapErrorCode
910
import java.io.ByteArrayOutputStream
1011
import java.io.File
1112
import java.io.FileOutputStream
@@ -17,6 +18,7 @@ fun Bitmap.encode(
1718
compressFormat: Bitmap.CompressFormat,
1819
quality: Double,
1920
asFile: Boolean,
21+
mapErrorHandler: MapErrorHandler,
2022
): String? =
2123
try {
2224
targetSize?.let { scale(it.width, it.height) }
@@ -32,6 +34,6 @@ fun Bitmap.encode(
3234
"data:image/$format;base64," + Base64.encodeToString(bytes, Base64.NO_WRAP)
3335
}
3436
} catch (e: Exception) {
35-
mapsLog("snapshot export failed", e)
37+
mapErrorHandler.report(RNMapErrorCode.SNAPSHOT_EXPORT_FAILED, "snapshot export failed", e)
3638
null
3739
}

example/src/hooks/useMapCallbacks.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ export function useMapCallbacks(
3131

3232
const onMapError = useNitroCallback(
3333
props.onMapError,
34-
useCallback((e: RNMapErrorCode) => console.log('Map error:', e), [])
34+
useCallback(
35+
(e: RNMapErrorCode, message: string) =>
36+
console.log('Map error:', RNMapErrorCode[e], message),
37+
[]
38+
)
3539
);
3640

3741
const onMapReady = useNitroCallback(

ios/GoogleMapViewImpl.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import UIKit
77
final class GoogleMapsViewImpl: UIView, GMSMapViewDelegate,
88
GMSIndoorDisplayDelegate {
99

10+
private let mapErrorHandler: MapErrorHandler
1011
private let locationHandler: LocationHandler
1112
private let markerBuilder: MapMarkerBuilder
1213
private var mapView: GMSMapView?
@@ -35,9 +36,11 @@ GMSIndoorDisplayDelegate {
3536

3637
init(
3738
frame: CGRect = .zero,
39+
mapErrorHandler: MapErrorHandler,
3840
locationHandler: LocationHandler,
3941
markerBuilder: MapMarkerBuilder
4042
) {
43+
self.mapErrorHandler = mapErrorHandler
4144
self.locationHandler = locationHandler
4245
self.markerBuilder = markerBuilder
4346
super.init(frame: frame)
@@ -468,7 +471,8 @@ GMSIndoorDisplayDelegate {
468471
format: format,
469472
imageFormat: imageFormat,
470473
quality: quality,
471-
resultIsFile: resultIsFile
474+
resultIsFile: resultIsFile,
475+
mapErrorHandler: self.mapErrorHandler
472476
) {
473477
promise.resolve(withResult: result)
474478
} else {

ios/MapErrorHandler.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Foundation
2+
3+
private let mapsLogTag = "react-native-google-maps-plus"
4+
5+
final class MapErrorHandler {
6+
7+
var callback: ((RNMapErrorCode, String) -> Void)?
8+
9+
func report(_ code: RNMapErrorCode, _ msg: String, _ error: Error? = nil) {
10+
if let error {
11+
NSLog("[%@] %@ | %@", mapsLogTag, msg, String(describing: error))
12+
} else {
13+
NSLog("[%@] %@", mapsLogTag, msg)
14+
}
15+
16+
onMain { [weak self] in
17+
guard let self else { return }
18+
self.callback?(code, msg)
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)