Mobile Integration (iOS & Android)
SmartMaps styles work natively with MapLibre Native on iOS and Android. Since SmartMaps uses the open MapLibre Style Specification, you can load any SmartMaps style.json directly, no proprietary SDK required.
Style URLs
All SmartMaps styles are available as standard style.json endpoints. Replace [INSERT API-KEY] with your actual API key:
| Style | URL |
|---|---|
| Light | https://tiles.smartmaps.cloud/styles/v1/smartmaps/light/style.json?apiKey=[INSERT API-KEY]&channel=app |
| Dark | https://tiles.smartmaps.cloud/styles/v1/smartmaps/dark/style.json?apiKey=[INSERT API-KEY]&channel=app |
| Grey | https://tiles.smartmaps.cloud/styles/v1/smartmaps/grey/style.json?apiKey=[INSERT API-KEY]&channel=app |
| Essential | https://tiles.smartmaps.cloud/styles/v1/smartmaps/essential/style.json?apiKey=[INSERT API-KEY]&channel=app |
| Accessible | https://tiles.smartmaps.cloud/styles/v1/smartmaps/accessible/style.json?apiKey=[INSERT API-KEY]&channel=app |
| Satellite | https://tiles.smartmaps.cloud/styles/v1/smartmaps/satellite/style.json?apiKey=[INSERT API-KEY]&channel=app |
For more details on each style, see the Style definition page.
MapSession (required)
Important
When using MapLibre Native directly (without the SmartMaps GL JS SDK), you must register a MapSession manually. The SmartMaps GL JS SDK handles this automatically, but native apps need to call the MapSession endpoint themselves.
SmartMaps uses MapSessions to track tile usage for billing. Your app must send a GET request to the MapSession endpoint periodically every 10 minutes while the map is active.
Endpoint:
GET https://www.yellowmap.de/api_rst/api/mapsessiongl?apiKey={API-KEY}&provider=smartmaps&channel=app
| Parameter | Required | Value |
|---|---|---|
apiKey |
Yes | Your SmartMaps API key (URL-encoded) |
provider |
Yes | smartmaps |
import java.net.URL
import java.net.URLEncoder
import java.util.Timer
import kotlin.concurrent.fixedRateTimer
class MapSessionManager(private val apiKey: String) {
private var timer: Timer? = null
fun start() {
// Send initial session request, then repeat every 10 minutes
timer = fixedRateTimer("mapsession", daemon = true, period = 600_000L) {
sendSession()
}
}
fun stop() {
timer?.cancel()
timer = null
}
private fun sendSession() {
Thread {
try {
val encodedKey = URLEncoder.encode(apiKey, "UTF-8")
val url = URL(
"https://www.yellowmap.de/api_rst/api/mapsessiongl?apiKey=$encodedKey&provider=smartmaps&channel=app"
)
val connection = url.openConnection() as java.net.HttpURLConnection
connection.requestMethod = "GET"
connection.responseCode // execute request
connection.disconnect()
} catch (e: Exception) {
e.printStackTrace()
}
}.start()
}
}
Usage in your Activity:
class MainActivity : AppCompatActivity() {
private val mapSession = MapSessionManager("[INSERT API-KEY]")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ... map setup ...
mapSession.start()
}
override fun onDestroy() {
mapSession.stop()
super.onDestroy()
}
}
import Foundation
class MapSessionManager {
private let apiKey: String
private var timer: Timer?
init(apiKey: String) {
self.apiKey = apiKey
}
func start() {
// Send initial session request
sendSession()
// Repeat every 10 minutes
timer = Timer.scheduledTimer(withTimeInterval: 600, repeats: true) { [weak self] _ in
self?.sendSession()
}
}
func stop() {
timer?.invalidate()
timer = nil
}
private func sendSession() {
guard let encodedKey = apiKey.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let url = URL(string:
"https://www.yellowmap.de/api_rst/api/mapsessiongl?apiKey=\(encodedKey)&provider=smartmaps&channel=app"
) else { return }
URLSession.shared.dataTask(with: url) { _, _, _ in }.resume()
}
}
Usage in UIKit:
class MapViewController: UIViewController {
private let mapSession = MapSessionManager(apiKey: "[INSERT API-KEY]")
override func viewDidLoad() {
super.viewDidLoad()
// ... map setup ...
mapSession.start()
}
deinit {
mapSession.stop()
}
}
Usage in SwiftUI:
struct SmartMapsMapView: View {
@StateObject private var mapSession = MapSessionObservable(apiKey: "[INSERT API-KEY]")
var body: some View {
MapView(styleURL: styleURL)
.onAppear { mapSession.start() }
.onDisappear { mapSession.stop() }
}
}
class MapSessionObservable: ObservableObject {
private let manager: MapSessionManager
init(apiKey: String) { manager = MapSessionManager(apiKey: apiKey) }
func start() { manager.start() }
func stop() { manager.stop() }
}
Android
Prerequisites
- Android Studio
- Min SDK 21 (Android 5.0) or higher
- A SmartMaps API key (register for free)
Setup
Add the MapLibre Native dependency to your build.gradle.kts (module-level):
Map with XML Layout
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.maplibre.android.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import org.maplibre.android.MapLibre
import org.maplibre.android.maps.MapView
import org.maplibre.android.maps.Style
import org.maplibre.android.camera.CameraPosition
import org.maplibre.android.geometry.LatLng
class MainActivity : AppCompatActivity() {
private lateinit var mapView: MapView
private val styleUrl =
"https://tiles.smartmaps.cloud/styles/v1/smartmaps/light/style.json?apiKey=[INSERT API-KEY]&channel=app"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MapLibre.getInstance(this)
setContentView(R.layout.activity_main)
mapView = findViewById(R.id.mapView)
mapView.onCreate(savedInstanceState)
mapView.getMapAsync { map ->
map.setStyle(styleUrl)
map.cameraPosition = CameraPosition.Builder()
.target(LatLng(51.1657, 10.4515))
.zoom(6.0)
.build()
}
}
override fun onStart() { super.onStart(); mapView.onStart() }
override fun onResume() { super.onResume(); mapView.onResume() }
override fun onPause() { super.onPause(); mapView.onPause() }
override fun onStop() { super.onStop(); mapView.onStop() }
override fun onDestroy() { super.onDestroy(); mapView.onDestroy() }
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
override fun onLowMemory() { super.onLowMemory(); mapView.onLowMemory() }
}
Jetpack Compose
MapLibre Native also provides a Jetpack Compose extension:
dependencies {
implementation("org.maplibre.gl:android-sdk:11.8.5")
implementation("org.maplibre.gl:android-sdk-compose:0.2.0")
}
import org.maplibre.android.compose.MapView
import org.maplibre.android.compose.CameraPosition
import org.maplibre.android.geometry.LatLng
@Composable
fun SmartMapsMap() {
MapView(
styleUri = "https://tiles.smartmaps.cloud/styles/v1/smartmaps/light/style.json?apiKey=[INSERT API-KEY]&channel=app",
cameraPosition = CameraPosition(
target = LatLng(51.1657, 10.4515),
zoom = 6.0
)
)
}
Adding a Marker
mapView.getMapAsync { map ->
map.setStyle(styleUrl) { style ->
// Add a marker at Karlsruhe
map.addMarker(
MarkerOptions()
.position(LatLng(49.0069, 8.4037))
.title("Karlsruhe")
.snippet("SmartMaps Headquarters")
)
}
}
For the full Android API reference, see the MapLibre Native Android documentation.
iOS
Prerequisites
- Xcode 15 or later
- iOS 14.0+ deployment target
- A SmartMaps API key (register for free)
Setup with Swift Package Manager
In Xcode, go to File > Add Package Dependencies and add:
For SwiftUI support, also add:
UIKit
import UIKit
import MapLibre
class MapViewController: UIViewController {
private var mapView: MLNMapView!
override func viewDidLoad() {
super.viewDidLoad()
let styleURL = URL(string:
"https://tiles.smartmaps.cloud/styles/v1/smartmaps/light/style.json?apiKey=[INSERT API-KEY]&channel=app"
)!
mapView = MLNMapView(frame: view.bounds, styleURL: styleURL)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.setCenter(
CLLocationCoordinate2D(latitude: 51.1657, longitude: 10.4515),
zoomLevel: 6,
animated: false
)
view.addSubview(mapView)
}
}
SwiftUI
import SwiftUI
import MapLibre
import MapLibreSwiftUI
struct SmartMapsMapView: View {
let styleURL = URL(string:
"https://tiles.smartmaps.cloud/styles/v1/smartmaps/light/style.json?apiKey=[INSERT API-KEY]&channel=app"
)!
var body: some View {
MapView(styleURL: styleURL)
.initialViewport(
.centerAndZoom(
center: CLLocationCoordinate2D(
latitude: 51.1657,
longitude: 10.4515
),
zoom: 6
)
)
}
}
Adding an Annotation
func mapView(_ mapView: MLNMapView, didFinishLoading style: MLNStyle) {
let annotation = MLNPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(
latitude: 49.0069,
longitude: 8.4037
)
annotation.title = "Karlsruhe"
annotation.subtitle = "SmartMaps Headquarters"
mapView.addAnnotation(annotation)
}
For the full iOS API reference, see the MapLibre Native iOS documentation.
Using SmartMaps REST APIs on Mobile
All SmartMaps geo services are available as REST APIs and can be called directly from native apps using standard HTTP clients. This includes:
- Geocoding API - Convert addresses to coordinates and vice versa
- Routing API - Calculate routes, isochrones, and distance matrices
- Autocomplete API - Real-time address suggestions for search inputs
- Elevation API - Retrieve elevation data for geographic points
- Timezone API - Determine timezones for any location
- Area API - Query administrative boundaries
- Weather API - Current weather and forecasts
These APIs return standard JSON responses and work with any HTTP client (URLSession on iOS, OkHttp/Retrofit on Android).
Switching Styles at Runtime
You can switch between SmartMaps styles dynamically, for example to support light/dark mode:
// React to system dark mode
val isDarkMode = resources.configuration.uiMode and
Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
val styleUrl = if (isDarkMode) {
"https://tiles.smartmaps.cloud/styles/v1/smartmaps/dark/style.json?apiKey=[INSERT API-KEY]&channel=app"
} else {
"https://tiles.smartmaps.cloud/styles/v1/smartmaps/light/style.json?apiKey=[INSERT API-KEY]&channel=app"
}
map.setStyle(styleUrl)
// React to system dark mode
let styleName: String = {
switch UITraitCollection.current.userInterfaceStyle {
case .dark: return "dark"
default: return "light"
}
}()
let styleURL = URL(string:
"https://tiles.smartmaps.cloud/styles/v1/smartmaps/\(styleName)/style.json?apiKey=[INSERT API-KEY]&channel=app"
)!
mapView.styleURL = styleURL