DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • How To Create a Homescreen Widget in Android
  • Transitioning From Groovy to Kotlin for Gradle Android Projects
  • Java Vs. Kotlin: Which One Will Be the Best in 2019?
  • Issue and Present Verifiable Credentials With Spring Boot and Android

Trending

  • Navigating Change Management: A Guide for Engineers
  • Apache Spark 4.0: Transforming Big Data Analytics to the Next Level
  • How To Introduce a New API Quickly Using Quarkus and ChatGPT
  • Strategies for Securing E-Commerce Applications
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Geocoding Addresses With Kotlin and HERE in Android

Geocoding Addresses With Kotlin and HERE in Android

Get started with Kotlin and HERE for Android app development.

By 
Nic Raboy user avatar
Nic Raboy
·
Feb. 18, 19 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
11.1K Views

Join the DZone community and get the full member experience.

Join For Free

About a month or so ago, I had written a tutorial around geocoding addresses to their latitude and longitude equivalent and then displaying them on a map in Android using the HERE Geocoder API. In this previous tutorial, the HERE Android SDK was being used with Java. However, Java isn’t the only way to develop Android mobile applications, and it is actually becoming lesser used than the alternatives.

Instead, Kotlin is becoming increasingly popular and is slowly becoming the recommended approach towards developing native Android applications. While different languages, Kotlin and Java are similar.

In this tutorial, we’re going to learn how to display geocoded addresses on a map in Android using Kotlin and HERE.

To get an idea of what we hope to accomplish, take a look at the following animated image:

kotlin-android-here-geocoder

As you can see, nothing particularly fancy is happening. We’re accepting user input and we’re taking that input to display a marker on the map. In fact, this is the same thing we did in the previous tutorial, which focused on Java.

Developing an Android Application That Accepts User Input

We’re going to assume that you already have a Kotlin-based Android application that is configured to use the HERE Android SDK. If you haven’t configured the HERE Android SDK with Kotlin, check out my previous tutorial on the subject. As long as you’ve got a map displaying, we can jump right into the core points of this tutorial.

We’re going to focus on interacting with an EditText component before we focus on the HERE functionality. This means the first step is to include such a component in our activity_main.xml file:

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

    <EditText
            android:id="@+id/query"
            android:hint="Query..."
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:inputType="text"/>

    <fragment
            class="com.here.android.mpa.mapping.SupportMapFragment"
            android:id="@+id/mapfragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

</LinearLayout>


Notice that we’re included the EditText and given a specific variable id. We’ll be referencing this component based on its id in the Kotlin code.

With the XML updated for user input, let’s start editing the project’s MainActivity.kt file:

package com.example.raboy

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.widget.EditText
import com.here.android.mpa.common.GeoCoordinate
import com.here.android.mpa.common.OnEngineInitListener
import com.here.android.mpa.mapping.Map
import com.here.android.mpa.mapping.SupportMapFragment
import com.here.android.mpa.mapping.MapMarker
import com.here.android.mpa.search.ErrorCode
import com.here.android.mpa.search.GeocodeRequest2
import android.view.View


class MainActivity : AppCompatActivity() {

    private var map : Map = Map()
    private var mapFragment : SupportMapFragment = SupportMapFragment()
    private lateinit var editText : EditText

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mapFragment = getSupportFragmentManager().findFragmentById(R.id.mapfragment) as SupportMapFragment
        mapFragment.init { error ->
            if (error == OnEngineInitListener.Error.NONE) {
                map = mapFragment.map
                map.setCenter(GeoCoordinate(37.7397, -121.4252, 0.0), Map.Animation.NONE)
                map.zoomLevel = (map.maxZoomLevel + map.minZoomLevel) / 2
            }
        }
        editText = findViewById(R.id.query)

        editText.setOnKeyListener(View.OnKeyListener { _, keyCode, keyevent ->
            if (keyCode == KeyEvent.KEYCODE_ENTER && keyevent.action == KeyEvent.ACTION_UP) {
                // Logic to geocode here...
                editText.setText("")
                return@OnKeyListener true
            }
            false
        })
    }
}


If you followed my previous Kotlin tutorial, much of the above code will look familiar. The difference here is that we’re including an editText variable that we’re setting in the onCreate function. The editText variable is connected to our XML component.

Once we have reference to our component, we can create a listener for key events:

editText.setOnKeyListener(View.OnKeyListener { _, keyCode, keyevent ->
    if (keyCode == KeyEvent.KEYCODE_ENTER && keyevent.action == KeyEvent.ACTION_UP) {
        // Logic to geocode here...
        editText.setText("")
        return@OnKeyListener true
    }
    false
})


Using a lambda expression, we can check to see if the enter key was pressed. If pressed, we can choose to do some geocoding logic and then clear out the field so that further data can be input without having to erase manually.

There wasn’t much to it when it comes to getting user input support. Now, we can focus on taking that input and doing something with it.

Using the HERE Geocoder API to Place Markers on a Map

The idea is that when the enter key is pressed, we geocode the string and drop it on the map as a marker. To do this, we can create another function and some more class variables.

class MainActivity : AppCompatActivity() {

    private var map : Map = Map()
    private var mapFragment : SupportMapFragment = SupportMapFragment()
    private lateinit var marker : MapMarker
    private lateinit var editText : EditText

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mapFragment = getSupportFragmentManager().findFragmentById(R.id.mapfragment) as SupportMapFragment
        mapFragment.init { error ->
            if (error == OnEngineInitListener.Error.NONE) {
                map = mapFragment.map
                map.setCenter(GeoCoordinate(37.7397, -121.4252, 0.0), Map.Animation.NONE)
                map.zoomLevel = (map.maxZoomLevel + map.minZoomLevel) / 2
            }
        }
        editText = findViewById(R.id.query)

        editText.setOnKeyListener(View.OnKeyListener { _, keyCode, keyevent ->
            if (keyCode == KeyEvent.KEYCODE_ENTER && keyevent.action == KeyEvent.ACTION_UP) {
                dropMarker(editText.text.toString())
                editText.setText("")
                return@OnKeyListener true
            }
            false
        })
    }

    fun dropMarker(query: String) {
        if (::marker.isInitialized) {
            map.removeMapObject(marker)
        }
        val tracy = GeoCoordinate(37.7397, -121.4252)
        val request = GeocodeRequest2(query).setSearchArea(tracy, 5000)
        request.execute { results, error ->
            if (error != ErrorCode.NONE) {
                Log.e("HERE", error.toString())
            } else {
                for (result in results) {
                    marker = MapMarker()
                    marker.coordinate = GeoCoordinate(result.location.coordinate.latitude, result.location.coordinate.longitude, 0.0)
                    map.addMapObject(marker)
                }
            }
        }
    }
}


This time, we’ve created a marker variable. Since we don’t have any markers on the map when we launch our application, we don’t need to initialize this variable. All of our marker magic will take place in the dropMarker method.

In the dropMarker method, if the marker has already been initialized, we need to remove it from the map. In this example, we’ll only have one marker on the map at any given time. We’re also going to limit all of our geocoder requests to 5000 meters around the Tracy, CA area, which is specified by a set of latitude and longitude coordinates.

When it comes time to executing the geocoder, we’ll be left with potentially more than one result. Based on our logic, we’re going to loop through all the results, but only the last result will appear as a marker on the map. If you have a very specific query, you’ll likely only receive one result, but if you have a vague query like “elm,” the results might be more.

Conclusion

You just saw how to develop an Android application with Kotlin that made use of the HERE Geocoder API and various mapping features. Using Kotlin is an alternative to Java, which is what I demonstrated in a previous tutorial.

If you got stuck configuring the HERE Android SDK with Kotlin, check out my previous tutorial on the topic titled, Getting Started with HERE using Kotlin and the Android SDK.

Android (robot) Kotlin (programming language)

Published at DZone with permission of Nic Raboy, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How To Create a Homescreen Widget in Android
  • Transitioning From Groovy to Kotlin for Gradle Android Projects
  • Java Vs. Kotlin: Which One Will Be the Best in 2019?
  • Issue and Present Verifiable Credentials With Spring Boot and Android

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!