Google Maps in Compose Multiplatform
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:
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.