Skip to Content
ExamplesLayer Masking

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.

Northern Europe with Blue Marble imagery on land and plain white seas

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") ?: return

It 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.

© 2026 Xweather (opens in a new tab)Terms of Service (opens in a new tab)Privacy Policy (opens in a new tab)