Add live realtime data
Note
You can find the full source code of this example in RealTimeGeoJsonActivity.kt
of the MapLibreAndroidTestApp.
In this example you will learn how to add a live GeoJSON source. We have set up a lambda function that returns a new GeoJSON point every time it is called.
First we will create a GeoJSONSource
.
Adding GeoJSON source
try {
style.addSource(GeoJsonSource(ID_GEOJSON_SOURCE, URI(URL_GEOJSON_SOURCE)))
} catch (malformedUriException: URISyntaxException) {
Timber.e(malformedUriException, "Invalid URL")
}
Next we will create a SymbolLayer
that uses the source.
Adding a SymbolLayer source
val layer = SymbolLayer(ID_GEOJSON_LAYER, ID_GEOJSON_SOURCE)
layer.setProperties(
PropertyFactory.iconImage("plane"),
PropertyFactory.iconAllowOverlap(true)
)
style.addLayer(layer)
We use define a Runnable
and use android.os.Handler
with a android.os.Looper
to update the GeoJSON source every 2 seconds.
Defining a Runnable for updating the GeoJSON source
private inner class RefreshGeoJsonRunnable(
private val maplibreMap: MapLibreMap,
private val handler: Handler
) : Runnable {
override fun run() {
val geoJsonSource = maplibreMap.style!!.getSource(ID_GEOJSON_SOURCE) as GeoJsonSource
geoJsonSource.setUri(URL_GEOJSON_SOURCE)
val features = geoJsonSource.querySourceFeatures(null)
setIconRotation(features)
handler.postDelayed(this, 2000)
}
}
Bonus: set icon rotation
You can set the icon rotation of the icon when ever the point is updated based on the last two points.
Defining a Runnable for updating the GeoJSON source
if (features.size != 1) {
Timber.e("Expected only one feature")
return
}
val feature = features[0]
val geometry = feature.geometry()
if (geometry !is Point) {
Timber.e("Expected geometry to be a point")
return
}
if (lastLocation == null) {
lastLocation = geometry
return
}
maplibreMap.style!!.getLayer(ID_GEOJSON_LAYER)!!.setProperties(
PropertyFactory.iconRotate(calculateRotationAngle(lastLocation!!, geometry)),
)