Using open street map in kotlin

Using open street map in kotlin

Few months back I had come across Open Street Map because of one of my friend, that time the usage was for frontend purpose, this time while having a discussion with my senior, the thought of using Open Street Map for android came up and I tried it off.

We need to install the necessary dependancy

implementation("org.osmdroid:osmdroid-android:6.1.18")

For the coding part I found this medium article which made major part of coding a lot easier, but what it did allow me to do was to modify the code and what I did do was add the snippet to request for location permission, add a button that would take me right to my location as well as the functionality that zooms in the same place no matter how much you zoom out of the map.

The thing which I really liked about open street map is that it is full open source, no need of any kind of key to integrate, just plug and play.

class MainActivity : AppCompatActivity(), MapListener, LocationListener {
    private lateinit var mMap: MapView
    private lateinit var controller: IMapController
    private lateinit var mMyLocationOverlay: MyLocationNewOverlay
    private lateinit var locationManager: LocationManager
    private lateinit var binding: ActivityMainBinding
    private val targetZoomLevel = 20.0
    private val LOCATION_PERMISSION_REQUEST_CODE = 1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        Configuration.getInstance().load(
            applicationContext,
            getSharedPreferences(getString(R.string.app_name), MODE_PRIVATE)
        )
        mMap = binding.osmmap
        mMap.setTileSource(TileSourceFactory.MAPNIK)
        mMap.mapCenter
        mMap.setMultiTouchControls(true)
        mMap.getLocalVisibleRect(Rect())

        initializeMap()
    }

    private fun initializeMap() {
        mMyLocationOverlay = MyLocationNewOverlay(GpsMyLocationProvider(this), mMap)
        controller = mMap.controller

        mMyLocationOverlay.enableMyLocation()
        mMyLocationOverlay.enableFollowLocation()
        mMyLocationOverlay.isDrawAccuracyEnabled = true


        val myLocationButton = binding.myLocationButton
        myLocationButton.setOnClickListener {
// Get the current location from the MyLocationNewOverlay
            val myLocation = mMyLocationOverlay.myLocation

            if (myLocation != null) {
// Move the map to the current location
                controller.setCenter(myLocation)
                controller.animateTo(myLocation)
                controller.setZoom(targetZoomLevel)
            } else {
                Toast.makeText(this, "Location not available yet.", Toast.LENGTH_SHORT).show()
            }
        }

        Log.e("TAG", "onCreate:in ${controller.zoomIn()}")
        Log.e("TAG", "onCreate: out ${controller.zoomOut()}")

        mMap.overlays.add(mMyLocationOverlay)
        mMap.addMapListener(this)

// Initialize LocationManager
        locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
// Request location updates
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            requestLocationPermission()
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1f, this)
    }


    private fun requestLocationPermission() {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
            LOCATION_PERMISSION_REQUEST_CODE
        )
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        when (requestCode) {
            LOCATION_PERMISSION_REQUEST_CODE -> {
                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted, initialize the map
                    initializeMap()
                } else {
// Permission denied, handle accordingly (e.g., show a message to the user)
                    Toast.makeText(this, "Location permission denied.", Toast.LENGTH_SHORT).show()
                }
            }

            else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }

    override fun onScroll(event: ScrollEvent?): Boolean {
        Log.e("TAG", "onCreate:la ${event?.source?.mapCenter?.latitude}")
        Log.e("TAG", "onCreate:lo ${event?.source?.mapCenter?.longitude}")
        return true
    }

    override fun onZoom(event: ZoomEvent?): Boolean {
        Log.e("TAG", "onZoom zoom level: ${event?.zoomLevel} source: ${event?.source}")
        return false
    }

    override fun onLocationChanged(location: Location) {
// Handle location changes here
        Log.d("TAG", "Location changed: ${location.latitude}, ${location.longitude}")
    }

    override fun onProviderDisabled(provider: String) {
// Handle provider disabled
    }

    override fun onProviderEnabled(provider: String) {
// Handle provider enabled̵
    }


}
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<?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"
tools:context=".MainActivity">

<org.osmdroid.views.MapView
android:id="@+id/osmmap"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<Button
android:id="@+id/myLocationButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Show My Location" />

</RelativeLayout>

This is how the result looks like, of course it shoes even minute details and names of places nearby but of course I won't be revealing exact location.