Search code examples
androidgoogle-mapskotlinhighlight

How to add multiple GeoJsonLayer runtime and get click event in android


I am trying to add multiple GeoJsonLayer run time my requirement is on responce of api i have to highlight multiple countries in map which is working fine but i am not getting click event multiple layer i know only single layer click is only suppored by android but is ther a any way to add multiple layer and get separate click event of all event

this is my code

import android.location.Address
import android.location.Geocoder
import android.os.AsyncTask
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.gson.Gson
import com.google.maps.android.data.geojson.GeoJsonLayer
import com.google.maps.android.data.geojson.GeoJsonPolygonStyle
import org.json.JSONException
import org.json.JSONObject
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.net.URL
import java.util.*


class MapsNewActivity : AppCompatActivity(), OnMapReadyCallback {
    private val TAG = javaClass.simpleName
    private lateinit var mMap: GoogleMap

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_maps)
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        val mapFragment = supportFragmentManager
                .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)

    }

    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap

        mMap.setOnMapClickListener {
            val geocoder = Geocoder(this, Locale.getDefault())
            val addresses: List<Address> = geocoder.getFromLocation(it.latitude, it.longitude, 1)
            if (addresses.isNotEmpty()) {
                val country: String? = addresses[0].getCountryName()
                Log.e(TAG, "country is ${country.toString()}")
                Toast.makeText(this, country.toString(), Toast.LENGTH_SHORT).show()
            }
        }

        mMap.uiSettings.isZoomControlsEnabled = true

        val madrid = LatLng(40.416775, -3.70379)
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(madrid, 3f))

        retrieveFileFromUrl()
    }

    private fun retrieveFileFromUrl() {
        DownloadGeoJsonFile().execute("https://raw.githubusercontent.com/xomena-so/so41431384/master/app/src/main/res/raw/es_geojson.json")
        DownloadGeoJsonFile().execute("https://raw.githubusercontent.com/xomena-so/so41431384/master/app/src/main/res/raw/us_geojson.json")
    }

    inner class DownloadGeoJsonFile : AsyncTask<String?, Void?, GeoJsonLayer?>() {
        override fun doInBackground(vararg params: String?): GeoJsonLayer? {
            try {
                // Open a stream from the URL
                val stream = URL(params[0]).openStream()
                var line: String?
                val result = StringBuilder()
                val reader = BufferedReader(InputStreamReader(stream))
                while (reader.readLine().also { line = it } != null) {
                    // Read and save each line of the stream
                    result.append(line)
                }

                // Close the stream
                reader.close()
                stream.close()

                return GeoJsonLayer(mMap, JSONObject(result.toString()))
//                return JSONObject(result.toString())
            } catch (e: IOException) {
                Log.e(TAG, "GeoJSON file could not be read")
            } catch (e: JSONException) {
                Log.e(TAG, "GeoJSON file could not be converted to a JSONObject")
            }
            return null
        }

        override fun onPostExecute(layer: GeoJsonLayer?) {
            layer?.let { addGeoJsonLayerToMap(it) }
        }
    }

    private fun addGeoJsonLayerToMap(layer: GeoJsonLayer) {
        val style: GeoJsonPolygonStyle = layer.defaultPolygonStyle
        style.fillColor = R.color.map_highlight
        style.strokeColor = R.color.map_highlight_border
        style.strokeWidth = 1f
        layer.addLayerToMap()

        layer.setOnFeatureClickListener {
            Log.e(TAG, "layer click ${it.getProperty("title")}")
            Log.e(TAG, "layer click Data = = = ${Gson().toJson(it)}")
            Toast.makeText(
                this,
                "Feature clicked: " + it.getProperty("title"),
                Toast.LENGTH_SHORT
            ).show()

        }
    }
}

this is what I am getting

enter image description here

I am also getting a country name in toast on click of any other country but not getting a country name or click event in setOnFeatureClickListener or setOnMapClickListener on click of the highlighted part

so how do I get data on click of highlighted part in map?

Please help me how do I achieve this

Any help would be highly appreciated.


Solution

  • this is not the best solution but if you disable the click of the layer then you will get an event in setOnMapClickListener

    so I added this to get click event style.isClickable = false this will pervert the layer click event

    val style: GeoJsonPolygonStyle = layer.defaultPolygonStyle
            style.fillColor = R.color.map_highlight
            style.strokeColor = R.color.map_highlight_border
            style.strokeWidth = 1f
            style.isClickable = false // this will pervert setOnFeatureClickListener so  mMap.setOnMapClickListener work
            layer.addLayerToMap()
    

    you will receieve click event in this part

    mMap.setOnMapClickListener {
                val geocoder = Geocoder(this, Locale.getDefault())
                val addresses: List<Address> = geocoder.getFromLocation(it.latitude, it.longitude, 1)
                if (addresses.isNotEmpty()) {
                    val country: String? = addresses[0].getCountryName()
                    Log.e(TAG, "country is ${country.toString()}")
                    Toast.makeText(this, country.toString(), Toast.LENGTH_SHORT).show()
                }
            }
    

    this is working for me please do correct me if I am doing some wrong