Google Map integration with Movable Marker using kotlin

edited October 2023 in Android

Creating the layout for showing map

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">
    <fragment
        android:id="@+id/map"
        android:layout_below="@id/checkInToolbar"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

Functionality for showing map with movable marker


    companion object {
        const val LOCATION_PERMISSION_REQUEST_CODE = 1
        const val REQUEST_CHECK_SETTINGS = 2
    }
    var address=""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mapsBinding=ActivityGoogleMapsBinding.inflate(layoutInflater)
        sharedPreference = SharedPreference(this)
        setContentView(mapsBinding.root)

        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
        // fetchLocation()
                val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)

        locationCallback = object : LocationCallback() {
            override fun onLocationResult(p0: LocationResult){
                super.onLocationResult(p0)
                lastLocation = p0.lastLocation!!
                placeMarkerOnMap(LatLng(lastLocation.latitude, lastLocation.longitude))
            }
            }
        createLocationRequest()
    }

    internal fun placeMarkerOnMap(location: LatLng) {
        val markerOptions = MarkerOptions().position(location)
        marker?.remove()
        marker = mMap.addMarker(markerOptions)
        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(location, 20f))
      //  Log.d("TAG", "placeMarkerOnMap: $marker")

    

    @SuppressLint("LogConditional", "SetTextI18n")
    internal fun placeMarkerAtCurrentLocation(){
        if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            fusedLocationClient!!.lastLocation.addOnSuccessListener { location: Location? ->
                    location?.let {
                        val latLng = LatLng(it.latitude, it.longitude)
                        val markerOptions = MarkerOptions().position(latLng).title("My Location").draggable(true)
                        marker = mMap.addMarker(markerOptions)
                        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 20f)) // Zoom level can be adjusted
                    }
                }
                .addOnFailureListener { e ->
                    // Handle failure to get location
                }
        } else {
            // Request location permission if not granted
            // Handle the permission request, typically by using ActivityCompat.requestPermissions()
        }
    }


    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap
        mMap.setOnMarkerClickListener(this)
        mMap.setOnCameraIdleListener(this)
        setUpMap()

        placeMarkerAtCurrentLocation()
    }
    override fun onCameraIdle() {
        // Fetch the location details when the map camera stops moving
        val cameraPosition = mMap.cameraPosition.target
        fetchLocationDetails(cameraPosition)
        updateMarkerPosition(cameraPosition)
    }

    internal fun updateMarkerPosition(latLng: LatLng) {
      //  marker?.position = latLng
        if (marker == null) {
            // Create a new marker if it doesn't exist
            val markerOptions = MarkerOptions().position(latLng)
            marker = mMap.addMarker(markerOptions)
        } else {
            // Animate the marker to the new position
            val currentLatLng = marker!!.position
            val startPosition = currentLatLng.latitude to currentLatLng.longitude
            val endPosition = latLng.latitude to latLng.longitude

            val valueAnimator = ValueAnimator.ofFloat(0f, 1f)
            valueAnimator.duration = 100 // Animation duration in milliseconds
            valueAnimator.addUpdateListener { animation ->
                val fraction = animation.animatedFraction
                val newPosition = LatLng(
                    startPosition.first + fraction * (endPosition.first - startPosition.first),
                    startPosition.second + fraction * (endPosition.second - startPosition.second)
                )
                marker!!.position = newPosition
            }

            valueAnimator.start()
        }
    }
    private fun fetchLocationDetails(latLng: LatLng) {
        try {
            val geocoder = Geocoder(this, Locale.getDefault())
            val addresses = geocoder.getFromLocation(latLng.latitude, latLng.longitude, 1)

            if (addresses!!.isNotEmpty()) {
                 address = addresses[0].getAddressLine(0)
                val locationDetails = "${latLng.latitude} ${latLng.longitude}"
                mapsBinding.edtLocation.setText(locationDetails)
                mapsBinding.location.setOnClickListener {
                    sharedPreference.save("latlong",locationDetails)
                    val i = Intent(this@GoogleMapsActivity, BusinessdetailsActivity::class.java)
                    startActivity(i)
                }
    
            } 
        } catch (e: IOException) {
            e.printStackTrace()
            // Handle any errors that occur during geocoding, such as network issues.
        }
    }

    private fun setUpMap() {
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            mMap.isMyLocationEnabled = true
        } else {
            // Request location permission if not granted
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                LOCATION_PERMISSION_REQUEST_CODE
            )
        }

    }

    private fun createLocationRequest() {
        locationRequest = LocationRequest()
        locationRequest.interval = 10000
        locationRequest.fastestInterval = 5000
        locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY

        val builder = LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest)

        // 4
        val client = LocationServices.getSettingsClient(this)
        val task = client.checkLocationSettings(builder.build())

        // 5
        task.addOnSuccessListener {
            locationUpdateState = true
            startLocationUpdates()
        }
        task.addOnFailureListener { e ->
            if (e is ResolvableApiException) {
                // Location settings are not satisfied, but this can be fixed
                // by showing the user a dialog.
                try {
                    e.startResolutionForResult(
                        this,
                        REQUEST_CHECK_SETTINGS
                    )
                } catch (sendEx: IntentSender.SendIntentException) {
                    // Ignore the error.
                }
            }
        }
    }

    override fun onMarkerClick(p0: Marker): Boolean = false

    @Deprecated("Deprecated in Java")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CHECK_SETTINGS) {
            if (resultCode == Activity.RESULT_OK) {
                locationUpdateState = true
              
            }
        }
    }


Sign In or Register to comment.