Search the hospitals using Huawei Map Kit, Site Kit and Location Kit in Patient Tracking Android app (Kotlin) – Part 5
Tags: kotlin, map, location, site
Published: 2022-07-25 07:17:00



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wgj4381s4anrkuhg76r3.png)

**Introduction**
In this article, we can learn how to search the hospitals located by source and destination address with HMS Core Kits such as **Map**, **Site**, and **Location Kits**. Map kit is to display maps, it covers map data of more than **200** countries and regions for searching any location address. **Location kit** provides to get the current location and location updates, and it provides flexible location based services **globally** to the users. **Site kit** provides with convenient and secure access to diverse, place-related services to users.

So, I will provide a series of articles on this Patient Tracking App, in upcoming articles I will integrate other Huawei Kits.

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

[https://forums.developer.huawei.com/forumPortal/en/topic/0201902220661040078](https://forums.developer.huawei.com/forumPortal/en/topic/0201902220661040078)

[https://forums.developer.huawei.com/forumPortal/en/topic/0201908355251870119](https://forums.developer.huawei.com/forumPortal/en/topic/0201908355251870119)

[https://forums.developer.huawei.com/forumPortal/en/topic/0202914346246890032](https://forums.developer.huawei.com/forumPortal/en/topic/0202914346246890032)

[https://forums.developer.huawei.com/forumPortal/en/topic/0202920411340450018](https://forums.developer.huawei.com/forumPortal/en/topic/0202920411340450018)

**Map Kit**

Map Kit covers map data of more than 200 countries and regions, and supports over **70** languages. User can easily integrate map-based functions into your apps using SDK. It optimizes and enriches the map detail display capability. Map Kit supports gestures including **zoom**, **rotation**, **moving** and tilt gestures to ensure smooth interaction experience.

**Location Kit**

Location Kit combines the **GPS**, **Wi-Fi** and **base station** location functionalities in your app to build up global positioning capabilities, allows to provide flexible location-based services targeted at users around globally. Currently, it provides three main capabilities: **fused location**, **activity** **identification** and **geo-fence**. You can call one or more of these capabilities as required.

**Site Kit**

**Site Kit** provides the place related services for apps. It provides that to search places with keywords, find nearby place, place suggestion for user search, and find the place details using the unique id.

**Requirements**
1. Any operating system (MacOS, Linux and Windows).
2. Must have a Huawei phone with HMS 4.0.0.300 or later.
3. Must have a laptop or desktop with Android Studio, Jdk 1.8, SDK platform 26 and Gradle 4.6 and above installed.
4. Minimum API Level 24 is required.
5. Required EMUI 9.0.0 and later version devices.

**How to integrate HMS Dependencies**

- First register as Huawei developer and complete identity verification in Huawei developers website, refer to register a [Huawei ID](https://developer.huawei.com/consumer/en/doc/start/registration-and-verification-0000001053628148).

- Create a project in android studio, [refer Creating an Android Studio Project](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#1).

- Generate a **SHA-256 certificate fingerprint**.

- To generate **SHA-256 certificate fingerprint**. On right-upper corner of android project click **Gradle**, choose **Project Name > Tasks > android**, and then click **signingReport**, as follows.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/apc0rtsm9cfkkb6ihcxa.png)

Note: Project Name depends on the user created name.

- [Create an App in AppGallery Connect](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#0).

- Download the **agconnect-services.json** file from **App information**, copy and paste in android **Project** under **app** directory, as follows.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lpfnvdmr8i95nwrm48pu.png)


- Enter **SHA-256 certificate fingerprint** and click **Save** button, as follows.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrb2ugdz4dngw6qysm04.png)


- Click **Manage API**s tab and enable **Map Kit**, **Site Kit** and **Location Kit**.

- Add the below maven URL in **build.gradle(Project)** file under the repositories of **buildscript**, **dependencies** and **allprojects**, refer [Add Configuration](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#6).

```
maven { url 'http://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.6.0.300'

```

- Add the below plugin and dependencies in **build.gradle(Module)** file.

```
apply plugin: 'com.huawei.agconnect'
// Huawei AGC
implementation 'com.huawei.agconnect:agconnect-core:1.6.0.300'
// Huawei Map
implementation 'com.huawei.hms:maps:6.2.0.301'
// Huawei Site Kit
implementation 'com.huawei.hms:site:6.2.0.301'
// Huawei Location Kit
implementation 'com.huawei.hms:location:6.2.0.300'
```

- Now Sync the gradle.

- Add the required permission to the **AndroidManifest.xml** file.

```
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
// To obtain the coarse longitude and latitude of a user with Wi-Fi network or base station.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
// To receive location information from satellites through the GPS chip.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
```

**Let us move to development**

I have created a project on Android studio with empty activity let us start coding.

In the **SearchActivity.kt** we can find the business logic.

```
class SearchActivity : AppCompatActivity(), OnMapReadyCallback, View.OnClickListener {

    private lateinit var hmap: HuaweiMap
    private lateinit var mMapView: MapView
    private var mMarker: Marker? = null
    private var mCircle: Circle? = null
    private var isSourceAddressField: Boolean = false
    private var pickupLat: Double = 0.0
    private var pickupLng: Double = 0.0
    private var dropLat: Double = 0.0
    private var dropLng: Double = 0.0
    private var searchService: SearchService? = null
    private var searchIntent: SearchIntent? = null
    private lateinit var mFusedLocationProviderClient: FusedLocationProviderClient
    companion object {
        private const val TAG = "MapViewDemoActivity"
        private const val MAPVIEW_BUNDLE_KEY = "MapViewBundleKey"
        private val LAT_LNG = LatLng(12.9716, 77.5946)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_search)

        // Get mapView
        mMapView = findViewById(R.id.mapView)
        var mapViewBundle: Bundle? = null
        if (savedInstanceState != null) {
            mapViewBundle = savedInstanceState.getBundle(MAPVIEW_BUNDLE_KEY)
        }
        // Add "Your API key" in api_key field value
        MapsInitializer.setApiKey("DAEDADRgIFzXbAJpOqImvjRAGRkmm3wGTux0O6JBiaddIPMNTJ4SawIN8ZHWu28dtc1f1H3Cqzh0LC1cgYIvBnl1edWVuWkjciH4NA==")
        mMapView.onCreate(mapViewBundle)
        // get map by async method
        mMapView.getMapAsync(this)
        //Checking permission
        checkLocationPermission()
        // Location service
        mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
        //Initialize Search Service
        getLocationFromService()
        //Initialize OnClickListener
        customCurrentLocation.setOnClickListener(this)
        pickUpLocation.setOnClickListener(this)
        dropLocation.setOnClickListener(this)

    }

    override fun onMapReady(map: HuaweiMap?) {
        Log.d(TAG, "onMapReady: ")
        // Get the HuaweiMap instance in this call back method.
        hmap = map!!
        // Move camera by CameraPosition param, latlag and zoom params can set here.
        val build = CameraPosition.Builder().target(LatLng(13.0827, 80.2707)).zoom(10f).build()
        val cameraUpdate = CameraUpdateFactory.newCameraPosition(build)
        hmap.animateCamera(cameraUpdate)
        hmap.setMaxZoomPreference(10f)
        hmap.setMinZoomPreference(1f)
        // Marker can be add by HuaweiMap
        mMarker = hmap.addMarker(
            MarkerOptions().position(LAT_LNG)
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.garden_icon))
                .clusterable(true))
        mMarker?.showInfoWindow()
        // circle can be add by HuaweiMap
        mCircle = hmap.addCircle(
            CircleOptions().center(LatLng(28.7041, 77.1025)).radius(45000.0).fillColor(Color.GREEN))
        mCircle?.fillColor = Color.TRANSPARENT

    }

    override fun onStart() {
        super.onStart()
        mMapView.onStart()
    }
    override fun onStop() {
        super.onStop()
        mMapView.onStop()
    }
    override fun onDestroy() {
        super.onDestroy()
        mMapView.onDestroy()
    }
    override fun onPause() {
        mMapView.onPause()
        super.onPause()
    }
    override fun onResume() {
        super.onResume()
        mMapView.onResume()
    }

    private fun checkLocationPermission() {
        // check location permission
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
            if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                val strings = arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)
                ActivityCompat.requestPermissions(this, strings, 1)
            }
        }  else {
            if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this,ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this,"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
                val strings = arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION,
                    "android.permission.ACCESS_BACKGROUND_LOCATION")
                ActivityCompat.requestPermissions(this, strings, 2)
            }
        }
    }

    private fun getLocationFromService() {
        // Add your API Key in encode
        searchService = SearchServiceFactory.create(this,
            URLEncoder.encode("Add your api_key"))
    }

    override fun onClick(v: View?) {
        val id = v?.id
        if (id == R.id.pickUpLocation) {
            locationBox(100)
        } else if (id == R.id.dropLocation) {
            locationBox(101)
        } else if (id == R.id.customCurrentLocation) {
            getLastLocation()
        }
    }

    private fun locationBox(requestcode: Int) {
        searchIntent = SearchIntent()
        searchIntent!!.setApiKey(URLEncoder.encode("DAEDADRgIFzXbAJpOqImvjRAGRkmm3wGTux0O6JBiaddIPMNTJ4SawIN8ZHWu28dtc1f1H3Cqzh0LC1cgYIvBnl1edWVuWkjciH4NA==", "utf-8"))
        val intent = searchIntent!!.getIntent(this)
        startActivityForResult(intent, requestcode)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, @Nullable data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == 100) {
            if (SearchIntent.isSuccess(resultCode)) {
                isSourceAddressField = true
                val site: Site = searchIntent!!.getSiteFromIntent(data)
                pickUpLocation.setText(site.name)
                querySuggestion()
            }
        }
        if (requestCode == 101) {
            if (SearchIntent.isSuccess(resultCode)) {
                isSourceAddressField = false
                val site: Site = searchIntent!!.getSiteFromIntent(data)
                dropLocation.setText(site.name)
                querySuggestion()
            }
        }
    }

    private fun querySuggestion() {
        val request = QuerySuggestionRequest()
        val query: String?
        if (isSourceAddressField) {
            query = pickUpLocation?.text.toString()
        }else{
            query = dropLocation?.text.toString()
        }
        if (!TextUtils.isEmpty(query)) {
            request.query = query
        }
        searchService?.querySuggestion(
            request,
            searchResultListener as SearchResultListener<QuerySuggestionResponse>?
        )
    }

    private var searchResultListener =
        object : SearchResultListener<QuerySuggestionResponse> {
            override fun onSearchResult(results: QuerySuggestionResponse?) {
                val stringBuilder = StringBuilder()
                results?.let {
                    val sites = results.sites
                    if (sites != null && sites.size > 0) {
                        for (site in sites) {
                            val location = site.location
                            if (isSourceAddressField) {
                                pickupLat = location.lat
                                pickupLng = location.lng
                                moveCamera(LatLng(pickupLat, pickupLng))
                            } else {
                                dropLat = location.lat
                                dropLng = location.lng
                                moveCamera(LatLng(dropLat, dropLng))
                            }
                            break
                        }
                    } else {
                        stringBuilder.append("0 results")
                    }
                }
            }
            override fun onSearchError(status: SearchStatus) {
            }
        }

    private fun getLastLocation() {
        try {
            val lastLocation = mFusedLocationProviderClient.lastLocation
            lastLocation.addOnSuccessListener(OnSuccessListener { location ->
                if (location == null) {
                    return@OnSuccessListener
                }
                moveCamera(LatLng(location.latitude, location.longitude))
                return@OnSuccessListener
            }).addOnFailureListener { e ->
            }
        } catch (e: Exception) {
        }
    }

    private fun moveCamera(latLng: LatLng) {
        hmap!!.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
    }

}
```


In the **activity_search.xml** we can create the UI screen.

```
<?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:orientation="vertical"
    tools:context=".search.SearchActivity">

    <com.huawei.hms.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </com.huawei.hms.maps.MapView>

    <RelativeLayout
        android:id="@+id/startpoint"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="42dp"
        android:layout_marginTop="42dp"
        android:layout_marginRight="62dp"
        android:background="@drawable/blue_border_rounded_cornwe">

        <EditText
            android:id="@+id/pickUpLocation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/start_loc"
            android:background="@android:color/transparent"
            android:hint="Choose starting point "
            android:maxLines="1"
            android:paddingLeft="17dp"
            android:paddingTop="15dp"
            android:paddingBottom="15dp"
            android:textSize="13sp">
        </EditText>
        <ImageView
            android:id="@+id/start_loc"
            android:layout_width="20dp"
            android:layout_height="17dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="17dp"
            android:src="@drawable/start_icon" />
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="42dp"
        android:layout_marginTop="23dp"
        android:layout_marginRight="62dp"
        android:layout_below="@+id/startpoint"
        android:background="@drawable/blue_border_rounded_cornwe">
        <EditText
            android:id="@+id/dropLocation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/dest_loc"
            android:background="@android:color/transparent"
            android:hint="Password"
            android:maxLines="1"
            android:paddingLeft="17dp"
            android:paddingTop="15dp"
            android:paddingBottom="15dp"
            android:textSize="13sp">
        </EditText>
        <ImageView
            android:id="@+id/dest_loc"
            android:layout_width="20dp"
            android:layout_height="17dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="17dp"
            android:src="@drawable/dest_icon" />
    </RelativeLayout>

    <ImageView
        android:id="@+id/customCurrentLocation"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginRight="10dp"
        android:baselineAlignBottom="true"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:src="@drawable/location_icon"/>

</RelativeLayout>
```

**Demo**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9nifb36bi0cn86qfwy91.gif)


**Tips and Tricks**
1. Make sure you are already registered as Huawei developer.
2. Set minSDK version to 24 or later, otherwise you will get AndriodManifest merge issue.
3. Make sure you have added the agconnect-services.json file to app folder.
4. Make sure you have added SHA-256 fingerprint without fail.
5. Make sure all the dependencies are added properly.

**Conclusion**

In this article, we can learn how to search the hospitals located by source and destination address with HMS Core Kits such as Map, Site, and Location Kits. Map kit is to display maps, it covers map data of more than 200 countries and regions for searching any location address. Location kit provides to get the current location and location updates, and it provides flexible location based services globally to the users. Site kit provides with convenient and secure access to diverse, place-related services to users.

I hope you have read this article. If you found it is helpful, please provide likes and comments.

**Reference**

**Map Kit** - [Documentation](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/android-sdk-brief-introduction-0000001061991343)

**Map Kit** – [Training Video](https://developer.huawei.com/consumer/en/training/course/video/101590716045317017)

**Location Kit** – [Documentation](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/introduction-0000001050706106)

**Location Kit** – [Training Video](https://developer.huawei.com/consumer/en/training/course/video/101590715236705018)

[Site Kit](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/android-sdk-introduction-0000001050158571)