I'm trying to get the snapshot of a GoogleMap (from MapView) on background, return it with a callback and show it in an ImageView. While doing this, I'm trying to make getting snapshot part independent from the layout as much as possible (so, trying to avoid adding a MapView to the layout). What I've tried was creating a MapView programmatically with given size, adding some paths and pins on it, getting the snapshot and returning it (all subscribed using RxJava) but I'm getting the following error and app is closing without even a "app stopped working" dialog.
FATAL EXCEPTION: androidmapsapi-Snapshot Process: com.package.name.debug, PID: 2159 java.lang.IllegalArgumentException: width and height must be > 0 at android.graphics.Bitmap.createBitmap(Bitmap.java:1013) at android.graphics.Bitmap.createBitmap(Bitmap.java:980) at android.graphics.Bitmap.createBitmap(Bitmap.java:930) at android.graphics.Bitmap.createBitmap(Bitmap.java:891) at com.google.maps.api.android.lib6.impl.ec.b(:com.google.android.gms.DynamiteModulesB@11975940:4) at com.google.maps.api.android.lib6.impl.bf.run(:com.google.android.gms.DynamiteModulesB@11975940:4) at java.lang.Thread.run(Thread.java:764)
Here is the code for getting snapshot
fun bitmapFor(mapData: MapData, specs: Specs): Single<Bitmap?> {
val mapView = MapView(context)
mapView.layoutParams = ViewGroup.LayoutParams(specs.mapWidth, specs.mapHeight)
return mapView.getMap()
.subscribeOn(AndroidSchedulers.mainThread())
.map { googleMap ->
setupMap(googleMap, mapData) // Adds paths and pins
googleMap
}
.flatMap { googleMap ->
googleMap.snapshot(mapData)
}
}
private fun MapView.getMap(): Single<GoogleMap> {
return Single.create { subscriber ->
val handler = Handler(Looper.getMainLooper())
handler.post {
onCreate(null)
onStart()
onResume()
getMapAsync { googleMap ->
subscriber.onSuccess(googleMap)
}
}
}
}
private fun GoogleMap.snapshot(mapData: MapData): Single<Bitmap> {
return Single.create { subscriber ->
snapshot { bitmap ->
saveMap(mapData.hashCode().toString(), bitmap)
subscriber.onSuccess(bitmap)
}
}
}
And in the UI class, I'm doing
viewModel.mapProvider
.bitmapFor(map, viewModel.mapData, Specs(map.measuredWidth, map.measuredHeight))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onMap, this::onError) // onMap set's the image bitmap