DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Integration of Huawei Direction API in Navigation Glove IoT application Using Kotlin - Part 4
HMS Community
HMS Community

Posted on

Integration of Huawei Direction API in Navigation Glove IoT application Using Kotlin - Part 4

Introduction

In this series of article, we will learn about Navigation Glove application and also we will learn about integration of the Huawei Direction API in Navigation Glove IoT application. We will learn how to draw polyline on the map.

If you are new to this series of articles, follow my previous articles.

Beginner: Integration of Huawei Account kit in Navigation Glove IoT application Using Kotlin - Part 1

Beginner: Integration of Huawei Map kit in Navigation Glove IoT application Using Kotlin - Part 2

Beginner: Integration of Huawei Site kit in Navigation Glove IoT application Using Kotlin - Part 3

What is Direction API?

Huawei Map Kit provides a set of HTTP/HTTPS APIs, which you can use to build map data functions like route planning, Static map, Raster map.

Directions API is a set of HTTPS-based APIs it is used to plans routes. The direction API returns data in JSON format. You can parse and draw route on the map.

It has following types of routes:

Walking: You can plan route max 150 kilometers.

Cycling: You can plan route max 100 kilometers.

Driving: Driving route gives some following functions:

  1. It returns 3 routes for request.

  2. It supports 5 waypoints.

  3. It gives real time traffic condition.

Using Rest services we are integrating the following.

Direction API

Prerequisite

AppGallery Account
Android Studio 3.X
SDK Platform 19 or later
Gradle 4.6 or later
HMS Core (APK) 4.0.0.300 or later
Huawei Phone EMUI 3.0 or later
Non-Huawei Phone Android 4.4 or later
Service integration on AppGallery.

  1. We need to register as a developer account in AppGallery Connect.

  2. Create an app by referring to Creating a Project and Creating an App in the Project.

  3. Set the data storage location based on the current location.

  4. Enabling Map Kit Service on AppGallery Connect.

  5. Generating a Signing Certificate Fingerprint.

  6. Configuring the Signing Certificate Fingerprint.

  7. Get your agconnect-services.json file to the app root directory.

Client development

  1. Create android project in android studio IDE.

  2. Add the maven URL inside the repositories of buildscript and allprojects respectively (project level build.gradle file).

maven { url 'https://developer.huawei.com/repo/' }
Enter fullscreen mode Exit fullscreen mode
  1. Add the classpath inside the dependency section of the project level build.gradle file.
classpath 'com.huawei.agconnect:agcp:1.5.2.300'
Enter fullscreen mode Exit fullscreen mode
  1. Add the plugin in the app-level build.gradle file.
apply plugin: 'com.huawei.agconnect'
Enter fullscreen mode Exit fullscreen mode
  1. Add the below library in the app-level build.gradle file dependencies section.
implementation 'com.huawei.hms:maps:4.0.0.302'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
implementation 'com.squareup.retrofit2:converter-gson:2.7.2'
Enter fullscreen mode Exit fullscreen mode
  1. Add all the below permissions in the AndroidManifest.xml.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Enter fullscreen mode Exit fullscreen mode
  1. Sync the project.

By now user has select the Source location and Destination Location. And also we have added marker on the map.

Direction API Code

For direction API, we are using retrofit library to get the direction API.

So first let’s see what will be the Request and what will be response. And also end point.

Method Type: POST

URL: https://mapapi.cloud.huawei.com/mapApi/v1/routeService/driving?key=API key

Note: Replace API key with you project API key

Data Format: Request: Content-Type: application/json

                   Response: Content-Type: application/json
Enter fullscreen mode Exit fullscreen mode

Request Example

POST https://mapapi.cloud.huawei.com/mapApi/v1/routeService/driving?key=API key HTTP/1.1

**Content-Type: application/json

Accept: application/json**

{
   "destination":{
      "lat":12.982126,
      "lng":77.533103
   },
   "origin":{
      "lat":12.9702763,
      "lng":77.5373127
   }
}
Enter fullscreen mode Exit fullscreen mode

Response

HTTP/1.1 200 OK

Content-type: application/json

Just check it in the Postman or RestClient or any other tools which give response for HTTP request

Now let us set up

Step 1: Create Const class.

package com.huawei.navigationglove.api
object Const {
const val BASE_URL = "https://mapapi.cloud.huawei.com/mapApi/v1/"
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Create ApiClient class.

package com.huawei.navigationglove.api

import android.content.Context
import android.text.TextUtils

import okhttp3.Interceptor

import okhttp3.logging.HttpLoggingInterceptor

import okhttp3.OkHttpClient

import retrofit2.converter.gson.GsonConverterFactory

import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import okhttp3.HttpUrl
import okhttp3.Request

import retrofit2.Retrofit
import java.util.concurrent.TimeUnit

object ApiClient {
    private val retrofit: Retrofit = Retrofit.Builder()
        .baseUrl(Const.BASE_URL)
        .client(setInterceptors())
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    private fun setInterceptors(): OkHttpClient {
        val logger = HttpLoggingInterceptor()
        logger.level = HttpLoggingInterceptor.Level.BODY

        return OkHttpClient.Builder()
            .readTimeout(60, TimeUnit.SECONDS)
            .connectTimeout(60, TimeUnit.SECONDS)
            .addInterceptor { chain ->
                val url: HttpUrl = chain.request().url.newBuilder()
                    .addQueryParameter(
                        "key",
                        "ADD_YOUR_API_KEY_HERE"
                    )
                    .build()
                val request = chain.request().newBuilder()
                    .header("Content-Type", "application/json")
                    .url(url)
                    .build()
                chain.proceed(request)
            }
            .addInterceptor(logger)
            .build()
    }

    fun createApiService(): ApiService {
        return ApiClient.retrofit.create(ApiService::class.java)
    }

    fun <S> createService(serviceClass: Class<S>?): S {
        return retrofit.create(serviceClass)
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the ApiService interface.

package com.huawei.navigationglove.api

import com.huawei.navigationglove.api.request.DirectionRequest
import com.huawei.navigationglove.api.response.DirectionResponse
import io.reactivex.Single
import retrofit2.Call
import retrofit2.http.*

interface ApiService {
    @POST("routeService/{type}")
    fun getDirectionsWithType(
        @Path(value = "type",encoded = true) type : String,
        @Body directionRequest: DirectionRequest
    ): Call<DirectionResponse>
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Create TypeOfDirection Enum to get routes for driving/walking/cycling

package com.huawei.navigationglove.api
enum class TypeOfDirection(val type: String) {
WALKING("walking"),
BICYCLING("bicycling"),
DRIVING("driving")
}
Enter fullscreen mode Exit fullscreen mode

Before creating request and response class, let us add one plugin to convert from JSON to Kotlin data classes
Choose File > Setting > Plugin

Image description
Image description

Step 5: Now we need to create Request kotlin classes.
Image description
Image description

Origin.kt

package com.huawei.navigationglove.api.request

import com.google.gson.annotations.SerializedName

data class Origin(@SerializedName("lng")
                  val lng: Double = 0.0,
                  @SerializedName("lat")
                  val lat: Double = 0.0)
Enter fullscreen mode Exit fullscreen mode

Destination.kt

package com.huawei.navigationglove.api.request

import com.google.gson.annotations.SerializedName

data class Destination(@SerializedName("lng")
                       val lng: Double = 0.0,
                       @SerializedName("lat")
                       val lat: Double = 0.0)
Enter fullscreen mode Exit fullscreen mode

DirectionRequest.kt

package com.huawei.navigationglove.api.request

import com.google.gson.annotations.SerializedName

data class DirectionRequest(@SerializedName("origin")
                            val origin: Origin,
                            @SerializedName("destination")
                            val destination: Destination)
Enter fullscreen mode Exit fullscreen mode

Step 6: Now create Response Class. Same as the Request class created.
DirectionResponse.kt

package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class DirectionResponse(@SerializedName("routes")
                             val routes: List<RoutesItem>?,
                             @SerializedName("returnCode")
                             val returnCode: String = "",
                             @SerializedName("returnDesc")
                             val returnDesc: String = "")
Enter fullscreen mode Exit fullscreen mode

Bounds.kt

package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class Bounds(@SerializedName("southwest")
                  val southwest: Southwest,
                  @SerializedName("northeast")
                  val northeast: Northeast)
Enter fullscreen mode Exit fullscreen mode

EndLocation.kt

package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class EndLocation(@SerializedName("lng")
                       val lng: Double = 0.0,
                       @SerializedName("lat")
                       val lat: Double = 0.0)
Enter fullscreen mode Exit fullscreen mode

Northeast.kt


package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class Northeast(@SerializedName("lng")
                     val lng: Double = 0.0,
                     @SerializedName("lat")
                     val lat: Double = 0.0)
Enter fullscreen mode Exit fullscreen mode

PathItems.kt


package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class PathsItem(@SerializedName("duration")
                     val duration: Double = 0.0,
                     @SerializedName("durationText")
                     val durationText: String = "",
                     @SerializedName("durationInTrafficText")
                     val durationInTrafficText: String = "",
                     @SerializedName("durationInTraffic")
                     val durationInTraffic: Double = 0.0,
                     @SerializedName("distance")
                     val distance: Double = 0.0,
                     @SerializedName("startLocation")
                     val startLocation: StartLocation,
                     @SerializedName("startAddress")
                     val startAddress: String = "",
                     @SerializedName("distanceText")
                     val distanceText: String = "",
                     @SerializedName("steps")
                     val steps: List<StepsItem>?,
                     @SerializedName("endLocation")
                     val endLocation: EndLocation,
                     @SerializedName("endAddress")
                     val endAddress: String = "")
Enter fullscreen mode Exit fullscreen mode

PolylineItems.kt

package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class PolylineItem(@SerializedName("lng")
                        val lng: Double = 0.0,
                        @SerializedName("lat")
                        val lat: Double = 0.0)
Enter fullscreen mode Exit fullscreen mode

RoutesItem.kt

package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class RoutesItem(@SerializedName("trafficLightNum")
                      val trafficLightNum: Int = 0,
                      @SerializedName("dstInDiffTimeZone")
                      val dstInDiffTimeZone: Int = 0,
                      @SerializedName("crossCountry")
                      val crossCountry: Int = 0,
                      @SerializedName("hasRestrictedRoad")
                      val hasRestrictedRoad: Int = 0,
                      @SerializedName("hasRoughRoad")
                      val hasRoughRoad: Int = 0,
                      @SerializedName("hasTrafficLight")
                      val hasTrafficLight: Int = 0,
                      @SerializedName("crossMultiCountries")
                      val crossMultiCountries: Int = 0,
                      @SerializedName("dstInRestrictedArea")
                      val dstInRestrictedArea: Int = 0,
                      @SerializedName("overviewPolyline")
                      val overviewPolyline: String = "",
                      @SerializedName("paths")
                      val paths: List<PathsItem>?,
                      @SerializedName("bounds")
                      val bounds: Bounds,
                      @SerializedName("hasTolls")
                      val hasTolls: Int = 0,
                      @SerializedName("hasFerry")
                      val hasFerry: Int = 0)
Enter fullscreen mode Exit fullscreen mode

Southwest.kt

package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class Southwest(@SerializedName("lng")
                     val lng: Double = 0.0,
                     @SerializedName("lat")
                     val lat: Double = 0.0)
Enter fullscreen mode Exit fullscreen mode

StartLocation.kt


package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class StartLocation(@SerializedName("lng")
                         val lng: Double = 0.0,
                         @SerializedName("lat")
                         val lat: Double = 0.0)
Enter fullscreen mode Exit fullscreen mode

StepsItem.kt


package com.huawei.navigationglove.api.response

import com.google.gson.annotations.SerializedName

data class StepsItem(@SerializedName("duration")
                     val duration: Double = 0.0,
                     @SerializedName("orientation")
                     val orientation: Int = 0,
                     @SerializedName("durationText")
                     val durationText: String = "",
                     @SerializedName("distance")
                     val distance: Double = 0.0,
                     @SerializedName("startLocation")
                     val startLocation: StartLocation,
                     @SerializedName("instruction")
                     val instruction: String = "",
                     @SerializedName("action")
                     val action: String = "",
                     @SerializedName("distanceText")
                     val distanceText: String = "",
                     @SerializedName("roadName")
                     val roadName: String = "",
                     @SerializedName("endLocation")
                     val endLocation: EndLocation,
                     @SerializedName("polyline")
                     val polyline: List<PolylineItem>?)
Enter fullscreen mode Exit fullscreen mode

Now everything set now call the API.

If your question about originReq and destinationReq follow my previous article. These two request has been created when user selects the source location and destination location.


        navigate.setOnClickListener {
            val directionRequest = DirectionRequest(originReq!!, destinationReq!!)
            getDirection(directionType, directionRequest)
        }
Enter fullscreen mode Exit fullscreen mode
private fun getDirection(directionType: String, directionRequest: DirectionRequest) {
        ApiClient.createApiService()
            .getDirectionsWithType(directionType, directionRequest)
            .enqueue(object : Callback<DirectionResponse> {
                override fun onFailure(call: Call<DirectionResponse>, t: Throwable) {
                    Toast.makeText(
                        this@HomeScreenActivity,
                        "Failure" + t.localizedMessage + "\n" + t.message,
                        Toast.LENGTH_SHORT
                    ).show()
                }

                override fun onResponse(
                    call: Call<DirectionResponse>,
                    response: Response<DirectionResponse>
                ) {
                    if (response.isSuccessful) {
                        response.body()?.let {
                            it.routes?.get(0)?.paths?.get(0)?.let { it1 -> addPolyLines(it1) }
                            Toast.makeText(this@HomeScreenActivity, "Success", Toast.LENGTH_SHORT)
                                .show()
                        }
                        //startActivity(Intent(this@HomeScreenActivity, MapsActivity::class.java))
                    }
                }

            })
    }
Enter fullscreen mode Exit fullscreen mode

Adding polyline


 var polyLine: Polyline? = null
    private fun addPolyLines(path: PathsItem) {
        if (polyLine != null) {
            polyLine!!.remove()
        }
        val options = PolylineOptions()
        options.add(LatLng(path.startLocation.lat, path.startLocation.lng))
        path.steps!!.forEach {
            it.polyline!!.forEach { it1 ->
                options.add(LatLng(it1.lat, it1.lng))
            }
        }
        options.add(LatLng(path.endLocation.lat, path.endLocation.lng))
        options.color(Color.BLACK)
        options.width(6f)
        polyLine = hMap!!.addPolyline(options)

    }
Enter fullscreen mode Exit fullscreen mode

Now let us see the full code.

HomeScreenActivity.kt


package com.huawei.navigationglove.ui

import android.content.Intent
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import com.huawei.hms.maps.*
import com.huawei.hms.maps.model.*
import com.huawei.hms.site.api.model.Site
import com.huawei.hms.site.widget.SearchIntent

import com.huawei.navigationglove.R
import com.huawei.navigationglove.api.ApiClient
import com.huawei.navigationglove.api.TypeOfDirection
import com.huawei.navigationglove.api.request.Destination
import com.huawei.navigationglove.api.request.DirectionRequest
import com.huawei.navigationglove.api.request.Origin
import com.huawei.navigationglove.api.response.DirectionResponse
import com.huawei.navigationglove.api.response.PathsItem

import kotlinx.android.synthetic.main.activity_home_screen.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.net.URLEncoder
import android.widget.RadioButton


class HomeScreenActivity : AppCompatActivity(), OnMapReadyCallback {
    private val TAG = HomeScreenActivity::class.java.name
    private val API_KEY: String =
        "Add your API Key here"
    private var originReq: Origin? = null
    private var destinationReq: Destination? = null
    var hMap: HuaweiMap? = null
    private val searchIntent = SearchIntent()
    private var mMarker: Marker? = null
    private var mCircle: Circle? = null
    private var directionType: String = TypeOfDirection.WALKING.type
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home_screen)
        val mSupportMapFragment: SupportMapFragment? =
            supportFragmentManager.findFragmentById(R.id.mapfragment_mapfragmentdemo) as SupportMapFragment?
        mSupportMapFragment!!.getMapAsync(this)

        //Site kit
        val apiKey = URLEncoder.encode(
            API_KEY,
            "utf-8"
        )
        searchIntent.setApiKey(apiKey)

        //Select source location
        start.setOnClickListener {
            //You can try the below one for older method
            //selectSourceLocation()
            /*val intent = searchIntent.getIntent(this)
            startActivityForResult(intent, SearchIntent.SEARCH_REQUEST_CODE)*/
            selectSourceLocation()
        }

        //Select Destination Location
        destination.setOnClickListener {
            selectDestinationLocation()
        }

        navigate.setOnClickListener {
            val directionRequest = DirectionRequest(originReq!!, destinationReq!!)
            getDirection(directionType, directionRequest)
        }

        directionTypeGroup.setOnCheckedChangeListener { group, checkedId -> // checkedId is the RadioButton selected
            val directionTypeRadioButton = findViewById<View>(checkedId) as RadioButton
            when (directionTypeRadioButton.text.toString().toLowerCase()) {
                "walking" -> directionType = TypeOfDirection.WALKING.type
                "driving" -> directionType = TypeOfDirection.DRIVING.type
                "cycling" -> directionType = TypeOfDirection.BICYCLING.type
            }
            Toast.makeText(applicationContext, directionTypeRadioButton.text, Toast.LENGTH_SHORT)
                .show()
        }
    }

    private fun selectSourceLocation() {
        val intent = searchIntent.getIntent(this)
        sourceLocationLauncher.launch(intent)
    }

    private var sourceLocationLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            val data: Intent? = result.data
            if (data != null) {
                if (SearchIntent.isSuccess(result.resultCode)) {
                    val site: Site = searchIntent.getSiteFromIntent(data)
                    start.text = site.getName()
                    originReq = Origin(site.location.lng, site.location.lat)
                    //originReq = Origin(-4.66529, 54.216608)
                    //Toast.makeText(application, site.getName(), Toast.LENGTH_LONG).show()
                    val build = CameraPosition.Builder()
                        .target(LatLng(site.location.lat, site.location.lng)).zoom(16f).build()
                    val cameraUpdate = CameraUpdateFactory.newCameraPosition(build)
                    hMap!!.animateCamera(cameraUpdate)
                    //Setting max and min zoom
                    //hMap!!.setMaxZoomPreference(10f)
                    //hMap!!.setMinZoomPreference(1f)
                    // Marker can be add by HuaweiMap
                    mMarker = hMap!!.addMarker(
                        MarkerOptions().position(LatLng(site.location.lat, site.location.lng))
                            .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_baseline_location_on_24))
                            .clusterable(true)
                    )
                    mMarker?.showInfoWindow()

                    // circle can be added to HuaweiMap
                    /*mCircle = hMap!!.addCircle(
                        CircleOptions().center(LatLng(28.7041, 77.1025)).radius(45000.0).fillColor(
                            Color.GREEN))
                    mCircle?.fillColor = Color.TRANSPARENT*/

                }
            } else {
                Toast.makeText(application, "Unable to find the data", Toast.LENGTH_LONG).show()
            }
        }

    private fun selectDestinationLocation() {
        val intent = searchIntent.getIntent(this)
        destinationLocationLauncher.launch(intent)
    }

    private var destinationLocationLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            val data: Intent? = result.data
            if (data != null) {
                if (SearchIntent.isSuccess(result.resultCode)) {
                    val site: Site = searchIntent.getSiteFromIntent(data)
                    destination.text = site.getName()
                    destinationReq = Destination(site.location.lng, site.location.lat)
                    //destinationReq = Destination(-4.66552, 54.2166)
                    val build = CameraPosition.Builder()
                        .target(LatLng(site.location.lat, site.location.lng)).zoom(16f).build()
                    val cameraUpdate = CameraUpdateFactory.newCameraPosition(build)

                    hMap!!.animateCamera(cameraUpdate)
                    mMarker = hMap!!.addMarker(
                        MarkerOptions().position(LatLng(site.location.lat, site.location.lng))
                            .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_baseline_destination_location_on_24))
                            .clusterable(true)
                    )
                    mMarker?.showInfoWindow()

                }
            } else {
                Toast.makeText(application, "Unable to find the data", Toast.LENGTH_LONG).show()
            }
        }

    override fun onMapReady(huaweiMap: HuaweiMap) {
        Log.d(TAG, "onMapReady: ")
        hMap = huaweiMap
        hMap!!.mapType = HuaweiMap.MAP_TYPE_NORMAL
        hMap!!.uiSettings.isMyLocationButtonEnabled = true

        // Add a polyline (mPolyline) to a map.
        /*  val mPolyline = hMap!!.addPolyline(
              PolylineOptions().add(
                  LatLng(47.893478, 2.334595),
                  LatLng(48.993478, 3.434595),
                  LatLng(48.693478, 2.134595),
                  LatLng(48.793478, 2.334595)
              )
          )
          // Set the color of the polyline (mPolyline) to red.
          mPolyline.color = Color.RED
          // Set the width of the polyline (mPolyline) to 10 pixels.
          mPolyline.width = 10f*/

        //Adding Polygon
        /*hMap!!.addPolygon(PolygonOptions().addAll(createRectangle(LatLng(12.9716, 77.5946), 0.1, 0.1))
                .fillColor(Color.GREEN)
                .strokeColor(Color.BLACK))*/

        //Adding Circle on the Map
        /*hMap!!.addCircle(CircleOptions()
            .center(LatLng(12.9716, 77.5946))
            .radius(500.0)
            .fillColor(Color.GREEN))*/


    }

    private fun createRectangle(
        center: LatLng,
        halfWidth: Double,
        halfHeight: Double
    ): List<LatLng> {
        return listOf(
            LatLng(center.latitude - halfHeight, center.longitude - halfWidth),
            LatLng(center.latitude - halfHeight, center.longitude + halfWidth),
            LatLng(center.latitude + halfHeight, center.longitude + halfWidth),
            LatLng(center.latitude + halfHeight, center.longitude - halfWidth)
        )
    }

    private fun getDirection(directionType: String, directionRequest: DirectionRequest) {
        ApiClient.createApiService()
            .getDirectionsWithType(directionType, directionRequest)
            .enqueue(object : Callback<DirectionResponse> {
                override fun onFailure(call: Call<DirectionResponse>, t: Throwable) {
                    Toast.makeText(
                        this@HomeScreenActivity,
                        "Failure" + t.localizedMessage + "\n" + t.message,
                        Toast.LENGTH_SHORT
                    ).show()
                }

                override fun onResponse(
                    call: Call<DirectionResponse>,
                    response: Response<DirectionResponse>
                ) {
                    if (response.isSuccessful) {
                        response.body()?.let {
                            it.routes?.get(0)?.paths?.get(0)?.let { it1 -> addPolyLines(it1) }
                            Toast.makeText(this@HomeScreenActivity, "Success", Toast.LENGTH_SHORT)
                                .show()
                        }
                        //startActivity(Intent(this@HomeScreenActivity, MapsActivity::class.java))
                    }
                }

            })
    }

    var polyLine: Polyline? = null
    private fun addPolyLines(path: PathsItem) {
        if (polyLine != null) {
            polyLine!!.remove()
        }
        val options = PolylineOptions()
        options.add(LatLng(path.startLocation.lat, path.startLocation.lng))
        path.steps!!.forEach {
            it.polyline!!.forEach { it1 ->
                options.add(LatLng(it1.lat, it1.lng))
            }
        }
        options.add(LatLng(path.endLocation.lat, path.endLocation.lng))
        options.color(Color.BLACK)
        options.width(6f)
        polyLine = hMap!!.addPolyline(options)

    }
}
Enter fullscreen mode Exit fullscreen mode

activity_home_screen.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:map="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=".ui.HomeScreenActivity">

    <fragment
        android:id="@+id/mapfragment_mapfragmentdemo"
        class="com.huawei.hms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        map:cameraTargetLat="12.9716"
        map:cameraTargetLng="77.5946"
        map:cameraZoom="10" />

    <androidx.cardview.widget.CardView
        android:id="@+id/cardview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|top"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"
        android:layout_marginRight="20dp"
        android:elevation="100dp"
        app:cardBackgroundColor="@android:color/white"
        app:cardCornerRadius="8dp">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <LinearLayout
                    android:id="@+id/locationLayout"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="9.5"
                    android:background="@color/white"
                    android:orientation="vertical"
                    android:padding="20dp">

                    <TextView
                        android:id="@+id/start"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginBottom="1dp"
                        android:background="@android:color/transparent"
                        android:hint="Choose a starting point..."
                        android:maxLines="1"
                        android:textColor="@color/purple_200"
                        android:textSize="18sp" />

                    <View
                        android:layout_width="match_parent"
                        android:layout_height="5dp"
                        android:layout_marginTop="5dp"
                        android:layout_marginRight="50dp"
                        android:layout_marginBottom="5dp"
                        android:background="@drawable/dottet_line" />

                    <TextView
                        android:id="@+id/destination"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:background="@android:color/transparent"
                        android:hint="Choose a destination..."
                        android:maxLines="1"
                        android:textSize="18sp"
                        android:textColor="@color/purple_200"/>
                </LinearLayout>

                <ImageView
                    android:id="@+id/navigate"
                    android:layout_width="36dp"
                    android:layout_height="36dp"
                    android:layout_gravity="center"
                    android:layout_marginRight="10dp"
                    android:layout_weight="0.5"
                    android:src="@drawable/ic_baseline_send_24" />

            </LinearLayout>
            <View
                android:layout_width="match_parent"
                android:layout_height="5dp"
                android:background="@drawable/dottet_line" />


            <RadioGroup
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:gravity="center"
                android:id="@+id/directionTypeGroup"
                android:orientation="horizontal">

                <RadioButton
                    android:id="@+id/walking"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_weight="1"
                    android:checked="true"
                    android:text="Walking" />

                <RadioButton
                    android:id="@+id/driving"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_weight="1"
                    android:text="Driving" />

                <RadioButton
                    android:id="@+id/cycling"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_weight="1"
                    android:text="Cycling" />
            </RadioGroup>

        </LinearLayout>
    </androidx.cardview.widget.CardView>

</FrameLayout>
Enter fullscreen mode Exit fullscreen mode

Result

Image description

Tips and Tricks

  1. Make sure you are already registered as a Huawei developer.

  2. Set min SDK version to 21 or later, otherwise you will get AndriodManifest to merge issue.

  3. Make sure you have added the agconnect-services.json file to the app folder.

  4. Make sure you have added the SHA-256 fingerprint without fail.

  5. Make sure all the dependencies are added properly.

  6. If you want location feature in the Map, make sure you add location permission in AndroidManifest.xml file.

  7. If you install app in android version 6 or greater than make sure you handled run time permission.

  8. Make sure you have encoded your API key with URLEncode UTF-8.

Conclusion

In this article, we have learnt the integration of the Direction API in Navigation Glove application using Android Studio and Kotlin. And also we have learnt how to convert the JSON to kotlin data classes. And also we have learnt the integration of the retrofit in the application.

Reference

Map Kit - Official document

Map Kit - Code lab

Map Kit - Training Video

Map Kit - Direction API

Top comments (0)

DEV runs on 100% open source code known as Forem.

Β 
Contribute to the codebase or host your own.
Β 
Check these out! πŸ‘‡