KMP Maps

repository·main·Indexed 42 days ago

https://github.com/software-mansion/kmp-maps

A unified map component for Compose Multiplatform applications providing integration with native map APIs on Android (Google Maps), iOS (Apple Maps or Google Maps), and Desktop (Google Maps JS via WebView). Features include customizable markers, GeoJSON and geometry support, location services, and interactive callbacks.

Tokens
3.6K
Snippets
10
Records
16
Agent score
53%

What's inside KMP Maps

  1. Overview of KMP Maps

    main

    kmp-maps is a unified map component for Compose Multiplatform applications. It provides seamless integration with native map APIs across Android, iOS, and Desktop, ensuring smooth performance and native gesture handling.

    Supported Platforms & Providers:

    • Android: Google Maps
    • iOS: Apple Maps or Google Maps
    • Desktop (JVM): Google Maps JS (via WebView)

    Key Features:

    • Customizable Markers: Build markers using standard Compose Multiplatform code.
    • GeoJSON Support: Render and style GeoJSON layers.
    • Geometry Support: Draw interactive circles, polygons, and polylines.
    • Location Services: Built-in handling for permissions and user location.
    • Interactive Callbacks: Event handling for clicks, camera movements, and POI interactions.
  2. Install KMP Maps via Gradle Version Catalogs

    main

    To install KMP Maps, first add the following entries to your gradle/libs.versions.toml file. You can choose between the core module (which uses Apple Maps on iOS and Google Maps on Android) or the googleMaps module (which uses Google Maps on both platforms).

    [versions]
    kmpMaps = "0.9.1"
    
    [libraries]
    # For native map (Apple Maps on iOS, Google Maps on Android)
    swmansion-kmpMaps-core = { module = "com.swmansion.kmpmaps:core", version.ref = "kmpMaps" }
    
    # For Google Maps (Google Maps on both platforms)
    swmansion-kmpMaps-googleMaps = { module = "com.swmansion.kmpmaps:google-maps", version.ref = "kmpMaps" }
  3. Configure your Google Maps API Key on iOS

    main

    You must provide a valid Google Maps API key to render maps on iOS. The method depends on your version of kmp-maps.

    Initialize the API key globally in your Kotlin code before any map rendering occurs using MapConfiguration.initialize.

    For Legacy Versions (Below 0.8.0)

    Add the API key directly to your iOS app target's Info.plist file.

    // Recommended for v0.8.0+
    MapConfiguration.initialize(googleMapsApiKey = "YOUR_API_KEY")
    <!-- Legacy (Below v0.8.0) in Info.plist -->
    <key>GoogleMapsAPIKey</key>
    <string>YOUR_API_KEY_HERE</string>
  4. Choose the correct Map import

    main

    Depending on your provider requirements, you must import the Map component from the specific package:

    1. Native Implementation: Uses native Google Maps on Android, native Apple Maps on iOS, and Google Maps JS API on desktop.

      • Import: com.swmansion.kmpmaps.core.Map
    2. Universal Google Maps: Uses Google Maps SDK on both Android and iOS, and Google Maps JS API on desktop.

      • Import: com.swmansion.kmpmaps.googlemaps.Map
  5. Add Google Maps SDK to iOS via CocoaPods

    main

    To use Google Maps on iOS, you must include the Google Maps SDK and the Google Maps iOS Utils library. Using CocoaPods involves configuring your shared KMP module and your iOS app's Podfile.

    1. Configure the iOS Podfile

    Create or update iosApp/Podfile. Ensure the pod name matches the podspec name produced by your KMP module (e.g., shared).

    2. Configure KMP cocoapods in build.gradle.kts

    In your shared module's build.gradle.kts, add the Google Maps dependencies within the cocoapods block and point to your Podfile.

    3. Installation Workflow

    Run the following commands to generate the necessary framework and install the pods:

    1. Generate the dummy framework: ./gradlew :shared:generateDummyFramework (replace :shared: with your module path).
    2. Navigate to the iOS directory: cd iosApp.
    3. Update and install: pod repo update && pod install.
    4. Open the project using the workspace: open iosApp.xcworkspace (always use .xcworkspace, never .xcodeproj).
    platform :ios, '16.0'
    
    target 'iosApp' do
      use_frameworks!
    
      # The Pod generated by KMP (name must match the podspec KMP produces)
      pod 'yourPodspecName', :path => '../' # e.g. 'shared'
    end
    // In shared module build.gradle.kts
    kotlin {
        cocoapods {
            // ... other config
            pod("GoogleMaps") { version = "10.4.0" }
            pod("Google-Maps-iOS-Utils") {
                version = "6.1.3"
                moduleName = "GoogleMapsUtils"
            }
            podfile = project.file("../iosApp/Podfile")
        }
    }
  6. Configure KMP Maps dependencies in build.gradle.kts

    main

    After updating your version catalog, add the chosen dependency to your shared module's build.gradle.kts file.

    Option A: Core (Apple Maps on iOS, Google Maps on Android):

    dependencies {
        implementation(libs.swmansion.kmpMaps.core)
    }

    Option B: Google Maps (Google Maps on both platforms):

    dependencies {
        implementation(libs.swmansion.kmpMaps.googleMaps)
    }
  7. Add Google Maps SDK to iOS via Swift Package Manager

    main

    If you prefer Swift Package Manager (SPM) over CocoaPods, add the following package URLs to your Xcode project. Set the Dependency Rule to Exact Version for both packages.

    • Google Maps SDK: https://github.com/googlemaps/ios-maps-sdk (Version 10.4.0)
    • Google Maps iOS Utils: https://github.com/googlemaps/google-maps-ios-utils (Version 6.1.3)
  8. Setup KMP Maps for Desktop (JVM)

    main

    The JVM desktop implementation relies on compose-webview-multiplatform (v1.7.0+), which requires KCEF to be initialized before the map is displayed.

    To use Google Maps on desktop, you must also initialize your API key globally using MapConfiguration.initialize(googleMapsApiKey = "...") before rendering the map.

    import dev.datlag.kcef.KCEF
    import java.io.File
    import kotlinx.coroutines.Dispatchers
    import kotlinx.coroutines.withContext
    
    fun main() = application {
        Window(title = "KMP Maps - Desktop", onCloseRequest = ::exitApplication) {
            var initialized by remember { mutableStateOf(false) }
    
            LaunchedEffect(Unit) {
                withContext(Dispatchers.IO) {
                    KCEF.init(
                        builder = {
                            installDir(File("kcef-bundle"))
                            progress { onInitialized { initialized = true } }
                            settings { noSandbox = true }
                        },
                        onError = { it?.printStackTrace() },
                    )
                }
            }
    
            if (initialized) {
                App()
            } else {
                Text("Initializing Map Engine...")
            }
        }
    }
    
    // For Google Maps on Desktop:
    MapConfiguration.initialize(googleMapsApiKey = "YOUR_API_KEY")