MapsGL Android - Adding a land mask to a raster layer
This example draws NASA Blue Marble imagery over land only. The imagery is a plain raster layer; what keeps it off the sea is a mask made from the built-in water layer, turned inside out.
It is the Android port of the MapsGL JS Adding a land mask to a raster layer example. The complete activity ships in the MapsGL Android SDK demo as LayerMaskingActivity.

A white water layer to mask with
The first layer is the ordinary water weather layer, with its fill set to white and added under the id water-mask:
val water = WeatherService.Water(controller.service)
water.layer.paint.fill?.color = StyleValue.Constant(Color.White)
val waterLayer = controller.addWeatherLayer(water, id = "water-mask") ?: returnIt does two jobs. Its geometry is what the raster is masked against, and since the raster will not draw over it, it is also what shows through wherever there is sea.
The Blue Marble tile source
The raster source is an ImageSourceDescriptor pointing at the Blue Marble tiles on the Xweather raster maps server. The example builds the URL itself, putting the account’s client id and secret into the path, and declares the tiles as 512 px since they are the @2x variant:
controller.addSource(
ImageSourceDescriptor(
id = "satellite-geocolor",
url = "$AMP_SERVER/${clientId}_$clientSecret/blue-marble/{z}/{x}/{y}/0@2x.png",
tileSize = TileSize(512),
),
)layerMask with invert makes it a land mask
The raster layer carries the mask as a LayerMaskSpec, which maps onto the JS mask object one field for one field:
controller.addLayer(
RasterLayerDescriptor(
id = "satellite",
source = "satellite-geocolor",
paint = RasterLayerPaint(opacity = 0.7f, raster = RasterPaint()),
layerMask = LayerMaskSpec(
layers = listOf(LayerMaskLayerConfig(id = waterLayer.id)),
invert = true,
),
),
beforeID = null,
)Without invert, a mask confines a layer to the mask layer’s geometry — here, the water. Inverting it lets the raster draw everywhere except there, which leaves it on land. The 0.7 opacity sits on RasterLayerPaint itself, where the JS example puts it under paint.raster.
The water layer has to exist first
layerMask is resolved into a GLES stencil when the masked layer is added, so the layer it names must already be on the map. That is why the raster refers to waterLayer.id, the id addWeatherLayer returned, and is added only after it.
Related
- Adding a custom raster layer — a raster tile source and layer without a mask