Zum Inhalt

Mobile-Integration (iOS & Android)

SmartMaps-Styles funktionieren nativ mit MapLibre Native unter iOS und Android. Da SmartMaps die offene MapLibre Style Specification verwendet, können Sie jede SmartMaps style.json direkt laden – ohne proprietäres SDK.

Style-URLs

Alle SmartMaps-Styles sind als Standard-style.json-Endpunkte verfügbar. Ersetzen Sie [INSERT API-KEY] durch Ihren tatsächlichen 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

Weitere Details zu den einzelnen Styles finden Sie auf der Seite Style-Definition.


MapSession (erforderlich)

Wichtig

Bei direkter Verwendung von MapLibre Native (ohne das SmartMaps GL JS SDK) müssen Sie eine MapSession manuell registrieren. Das SmartMaps GL JS SDK übernimmt dies automatisch, native Apps müssen den MapSession-Endpunkt jedoch selbst aufrufen.

SmartMaps verwendet MapSessions, um die Tile-Nutzung für die Abrechnung zu erfassen. Ihre App muss alle 10 Minuten periodisch eine GET-Anfrage an den MapSession-Endpunkt senden, solange die Karte aktiv ist.

Endpunkt:

GET https://www.yellowmap.de/api_rst/api/mapsessiongl?apiKey={API-KEY}&provider=smartmaps&channel=app
Parameter Erforderlich Wert
apiKey Ja Ihr SmartMaps API-Key (URL-codiert)
provider Ja 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()
    }
}

Verwendung in Ihrer 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()
    }
}

Verwendung 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()
    }
}

Verwendung 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

Voraussetzungen

Einrichtung

Fügen Sie die MapLibre-Native-Abhängigkeit zu Ihrer build.gradle.kts (Modul-Ebene) hinzu:

dependencies {
    implementation("org.maplibre.gl:android-sdk:11.8.5")
}

Karte mit 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 bietet außerdem eine Jetpack-Compose-Erweiterung:

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
        )
    )
}

Marker hinzufügen

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")
        )
    }
}

Die vollständige Android-API-Referenz finden Sie in der MapLibre Native Android-Dokumentation.


iOS

Voraussetzungen

Einrichtung mit Swift Package Manager

Gehen Sie in Xcode zu File > Add Package Dependencies und fügen Sie hinzu:

https://github.com/maplibre/maplibre-gl-native-distribution

Für SwiftUI-Unterstützung fügen Sie außerdem hinzu:

https://github.com/maplibre/swiftui-dsl

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
                )
            )
    }
}

Annotation hinzufügen

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)
}

Die vollständige iOS-API-Referenz finden Sie in der MapLibre Native iOS-Dokumentation.


Verwendung der SmartMaps REST-APIs auf Mobilgeräten

Alle SmartMaps-Geodienste sind als REST-APIs verfügbar und können direkt aus nativen Apps mit Standard-HTTP-Clients aufgerufen werden. Dazu gehören:

Diese APIs liefern Standard-JSON-Antworten und funktionieren mit jedem HTTP-Client (URLSession unter iOS, OkHttp/Retrofit unter Android).


Styles zur Laufzeit wechseln

Sie können zwischen SmartMaps-Styles dynamisch wechseln, um beispielsweise den Light-/Dark-Mode zu unterstützen:

// 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