Google Maps in Compose Multiplatform

Areeb Momin
3 min readSep 22, 2024

--

Map Thumbnail (AI Generated)

Introduction:

Compose Multiplatform is a Kotlin-based UI framework that allows developers to build cross-platform user interfaces for Android, iOS, Desktop, and Web using a shared codebase. It extends Jetpack Compose, enabling code reuse and seamless integration with platform-specific UI frameworks like SwiftUI on iOS. As Google Maps is not available for Compose Multiplatform we have integrated native SDK’s for Android and iOS.

Result:

Google Maps in Comopose Multiplatform

Sample Project:

Get API Key:

Let’s Code:

In commonMain:

Add expect composable in commonMain:

@Composable
expect fun MapComponent()

In androidMain:

Add dependency in module-level build.gradle.kts file:

implementation("com.google.maps.android:maps-compose:6.1.0")

Add API key in AndroidManifest.xml under <application> tag:

<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="MAPS_API_KEY" />

For best practices for adding Maps API key in Android follow the below Doc:

Note: Sample project follows this best practice.

Implement actual composable in androidMain:

@Composable
actual fun MapComponent() {
Box(
modifier = Modifier.fillMaxSize(),
) {
val coordinates = LatLng(19.068857, 72.833)
val markerState = rememberMarkerState(position = coordinates)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(coordinates, 10f)
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState
) {
Marker(
state = markerState,
title = "Bandra West",
snippet = "Mumbai"
)
}
}
}

In iosMain:

Update MainViewController.kt to add MapViewController callback:

fun MainViewController(
mapUIViewController: () -> UIViewController
) = ComposeUIViewController {
mapViewController = mapUIViewController
App()
}

lateinit var mapViewController: () -> UIViewController

Implement actual composable in iosMain:

@OptIn(ExperimentalForeignApi::class)
@Composable
actual fun MapComponent() {
UIKitViewController(
factory = mapViewController,
modifier = Modifier.fillMaxSize(),
)
}

In iosApp:

Add dependency for Google Maps via Swift Package Manager:

Provide API key on App’s init():

@main
struct iOSApp: App {
init() {
GMSServices.provideAPIKey("YOUR_API_KEY")
}

var body: some Scene {
WindowGroup {
ContentView()
}
}
}

Create GoogleMapView in SwiftUI:

struct GoogleMapView: UIViewRepresentable {
func makeUIView(context: Context) -> GMSMapView {
let options = GMSMapViewOptions()
options.camera = GMSCameraPosition.camera(withLatitude: 12.952636, longitude: 77.653059, zoom: 10.0)

let mapView = GMSMapView(options: options)

// Creates a marker in the center of the map.
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: 12.952636, longitude: 77.653059)
marker.title = "Indiranagar"
marker.snippet = "Bengaluru"
marker.map = mapView

return mapView
}

func updateUIView(_ uiView: GMSMapView, context: Context) {}
}

Provide GoogleMapView in MainViewController’s callback:

struct ComposeView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
MainViewControllerKt.MainViewController(
mapUIViewController: { () -> UIViewController in
return UIHostingController(rootView: GoogleMapView())
}
)
}

func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}

That’s it!

Drop your suggestions and improvements in the comment below. Peace.

Connect with me on LinkedIn.

--

--