Annotation: Marker
This guide will show you how to add Markers in the map.
Annotation
is an overlay on top of a Map. In package
org.maplibre.android.annotations
, it has the following subclasses:
A Marker shows an icon image at a geographical location. By default, marker uses a provided image as its icon.
Or, the icon can be customized using IconFactory to generate an Icon using a provided image.
For more customization, please read the documentation about MarkerOptions.
In this showcase, we continue the code from the Quickstart,
rename Activity into JsonApiActivity
,
and pull the GeoJSON data from a free and public API.
Then add markers to the map with GeoJSON:
- In your module Gradle file (usually
<project>/<app-module>/build.gradle
), addokhttp
to simplify code for making HTTP requests.
dependencies {
...
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
...
}
-
Sync your Android project the with Gradle files.
-
In
JsonApiActivity
we add a new variable forMapboxMap
. It is used to add annotations to the map instance.
class JsonApiActivity : AppCompatActivity() {
// Declare a variable for MapView
private lateinit var mapView: MapView
// Declare a variable for MapLibreMap
private lateinit var maplibreMap: MapLibreMap
- Call
mapview.getMapSync()
in order to get aMapboxMap
object. AftermaplibreMap
is assigned, call thegetEarthQuakeDataFromUSGS()
method to make a HTTP request and transform data into the map annotations.
mapView.getMapAsync { map ->
maplibreMap = map
maplibreMap.setStyle("https://demotiles.maplibre.org/style.json")
// Fetch data from USGS
getEarthQuakeDataFromUSGS()
}
- Define a function
getEarthQuakeDataFromUSGS()
to fetch GeoJSON data from a public API. If we successfully get the response, calladdMarkersToMap()
on the UI thread.
// Get Earthquake data from usgs.gov, read API doc at:
// https://earthquake.usgs.gov/fdsnws/event/1/
private fun getEarthQuakeDataFromUSGS() {
val url = "https://earthquake.usgs.gov/fdsnws/event/1/query".toHttpUrl().newBuilder()
.addQueryParameter("format", "geojson")
.addQueryParameter("starttime", "2022-01-01")
.addQueryParameter("endtime", "2022-12-31")
.addQueryParameter("minmagnitude", "5.8")
.addQueryParameter("latitude", "24")
.addQueryParameter("longitude", "121")
.addQueryParameter("maxradius", "1.5")
.build()
val request: Request = Request.Builder().url(url).build()
OkHttpClient().newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Toast.makeText(this@JsonApiActivity, "Fail to fetch data", Toast.LENGTH_SHORT)
.show()
}
override fun onResponse(call: Call, response: Response) {
val featureCollection = response.body?.string()
?.let(FeatureCollection::fromJson)
?: return
// If FeatureCollection in response is not null
// Then add markers to map
runOnUiThread { addMarkersToMap(featureCollection) }
}
})
}
- Now it is time to add markers into the map.
- In the
addMarkersToMap()
method, we define two types of bitmap for the marker icon. - For each feature in the GeoJSON, add a marker with a snippet about earthquake details.
- If the magnitude of an earthquake is bigger than 6.0, we use the red icon. Otherwise, we use the blue one.
- Finally, move the camera to the bounds of the newly added markers
- In the
private fun addMarkersToMap(data: FeatureCollection) {
val bounds = mutableListOf<LatLng>()
// Get bitmaps for marker icon
val infoIconDrawable = ResourcesCompat.getDrawable(
this.resources,
// Intentionally specify package name
// This makes copy from another project easier
org.maplibre.android.R.drawable.maplibre_info_icon_default,
theme
)!!
val bitmapBlue = infoIconDrawable.toBitmap()
val bitmapRed = infoIconDrawable
.mutate()
.apply { setTint(Color.RED) }
.toBitmap()
// Add symbol for each point feature
data.features()?.forEach { feature ->
val geometry = feature.geometry()?.toJson() ?: return@forEach
val point = Point.fromJson(geometry) ?: return@forEach
val latLng = LatLng(point.latitude(), point.longitude())
bounds.add(latLng)
// Contents in InfoWindow of each marker
val title = feature.getStringProperty("title")
val epochTime = feature.getNumberProperty("time")
val dateString = SimpleDateFormat("yyyy/MM/dd HH:mm", Locale.TAIWAN).format(epochTime)
// If magnitude > 6.0, show marker with red icon. If not, show blue icon instead
val mag = feature.getNumberProperty("mag")
val icon = IconFactory.getInstance(this)
.fromBitmap(if (mag.toFloat() > 6.0) bitmapRed else bitmapBlue)
// Use MarkerOptions and addMarker() to add a new marker in map
val markerOptions = MarkerOptions()
.position(latLng)
.title(dateString)
.snippet(title)
.icon(icon)
maplibreMap.addMarker(markerOptions)
}
// Move camera to newly added annotations
maplibreMap.getCameraForLatLngBounds(LatLngBounds.fromLatLngs(bounds))?.let {
val newCameraPosition = CameraPosition.Builder()
.target(it.target)
.zoom(it.zoom - 0.5)
.build()
maplibreMap.cameraPosition = newCameraPosition
}
}
- Here is the final result. For the full contents of
JsonApiActivity
, please visit source code of our Test App.