Get Current Location from Google Maps While Moving with Jetpack Compose

Published October 31, 2021

In this Jetpack compose tutorial we learn about how to get current location of the Camera from The Google Maps.When we move the maps camera will also moves and based on camera position we can get the current location of the camera and we can set marker on that position.

To get camera current position we add CameraIdleListener to the map and on idle state we will fetch the current position of the Map and get lat,longs from this position and show in the Textfield.

 

it.setOnCameraIdleListener {
   }

 

Let's get started

Step 1: Create Jetpack compose Proejct with android studio

Step 2: Add required dependencies to buid.gradle file

Step 3: Load Maps

AndroidView(
    {mapView}
) { mapView ->
    CoroutineScope(Dispatchers.Main).launch {


            mapView.getMapAsync {

}

}

 

Step 4: Add Camera Listener to the map and fetch current position data

it.setOnCameraIdleListener {
    it.clear()
    it.addMarker(MarkerOptions()
        .position(it.getCameraPosition().target))
    latlng.value=("lat: ${it.getCameraPosition().target.latitude}," +
            " \n lang: ${it.getCameraPosition().target.longitude}")
}

 

Step 5: Now let run the application, you can find the location updates from the camera while moving the map

 

Jetpack Compose Get Current Location of the Camera while moving the map

 

Complete code for Fetch Current Location of the Camera while moving the map

package com.rrtutors.compose_maps


import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.LocationOn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import com.google.android.libraries.maps.CameraUpdateFactory
import com.google.android.libraries.maps.GoogleMap
import com.google.android.libraries.maps.MapView
import com.google.android.libraries.maps.model.LatLng
import com.google.android.libraries.maps.model.MarkerOptions
import com.google.android.libraries.maps.model.PolylineOptions
import com.google.maps.android.ktx.addMarker
import com.google.maps.android.ktx.awaitMap
import com.rrtutors.compose_maps.ui.theme.ComposeMapsTheme
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeMapsTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    GoogleMaps()
                }
            }
        }
    }
}
@Composable
fun GoogleMaps() {

    var mapView = rememberMapViewWithLifeCycle()
var latlng= remember {   mutableStateOf("lat : 17.385,lang: 78.4867")}
    Box(){

        Column(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.White)
        ) {
            AndroidView(
                {mapView}
            ) { mapView ->
                CoroutineScope(Dispatchers.Main).launch {


                        mapView.getMapAsync {

                            it.mapType=1
                            it.uiSettings.isZoomControlsEnabled = true
                            val mark1 = LatLng(17.385, 78.4867) //Hyderabad


                            it.moveCamera(CameraUpdateFactory.newLatLngZoom(mark1, 12f))
                            it.setOnCameraIdleListener {
                                it.clear()
                                it.addMarker(MarkerOptions()
                                    .position(it.getCameraPosition().target))
                                latlng.value=("lat: ${it.getCameraPosition().target.latitude}," +
                                        " \n lang: ${it.getCameraPosition().target.longitude}")
                            }
                            val markerOptions =  MarkerOptions()
                                .title("Hyderabad")
                                .position(mark1)
                            it.addMarker(markerOptions)




                    }




                }
            }
        }

        Card (modifier = Modifier.background(Color.Transparent)
            .padding(12.dp)
            ,elevation = 10.dp
        ){
            OutlinedTextField( value =latlng.value,

                onValueChange = {

                },
                textStyle = TextStyle(
                    color = Color.Red,

                    fontFamily = FontFamily.SansSerif
                ),
                modifier = Modifier.background(Color.Transparent)
            , leadingIcon = {
                    // In this method we are specifying
                    // our leading icon and its color.
                    Icon(
                        imageVector = Icons.Default.LocationOn,
                        contentDescription = "image",
                        tint = Color.Green
                    )
                },
            )

        }


    }

}


@Composable
fun rememberMapViewWithLifeCycle(): MapView {
    val context = LocalContext.current
    val mapView = remember {
        MapView(context).apply {
            id = com.google.maps.android.ktx.R.id.map_frame
        }
    }
    val lifeCycleObserver = rememberMapLifecycleObserver(mapView)
    val lifeCycle = LocalLifecycleOwner.current.lifecycle
    DisposableEffect(lifeCycle) {
        lifeCycle.addObserver(lifeCycleObserver)
        onDispose {
            lifeCycle.removeObserver(lifeCycleObserver)
        }
    }

    return mapView
}

@Composable
fun rememberMapLifecycleObserver(mapView: MapView): LifecycleEventObserver =
    remember(mapView) {
        LifecycleEventObserver { _, event ->
            when(event) {
                Lifecycle.Event.ON_CREATE -> mapView.onCreate(Bundle())
                Lifecycle.Event.ON_START -> mapView.onStart()
                Lifecycle.Event.ON_RESUME -> mapView.onResume()
                Lifecycle.Event.ON_PAUSE -> mapView.onPause()
                Lifecycle.Event.ON_STOP -> mapView.onStop()
                Lifecycle.Event.ON_DESTROY -> mapView.onDestroy()
                else -> throw IllegalStateException()
            }
        }
    }

 

Conclusion: In this Jetpack compose tutorial we covered how to load Google Maps and add Camera Listeners to the Map and fetch current location of the Map while moving the camera

 

 

Download Source code

 

Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

3118 Views