[Huawei Developers] HMS Community:
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/0201908355251870119

https://forums.developer.huawei.com/forumPortal/en/topic/0202914346246890032

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

1. First register as Huawei developer and complete identity verification in Huawei developers website, refer to register a Huawei ID.

2. Create a project in android studio, refer Creating an Android Studio Project.

3. Generate a SHA-256 certificate fingerprint.

4. 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.

Note: Project Name depends on the user created name.

5. Create an App in AppGallery Connect.

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

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

Note: Above steps from Step 1 to 7 is common for all Huawei Kits.

8. Click Manage APIs tab and enable Map Kit, Site Kit and Location Kit.

9. Add the below maven URL in build.gradle(Project) file under the repositories of buildscript, dependencies and allprojects, refer Add Configuration.

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

10. 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'

11. Now Sync the gradle.

12. 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

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

Map Kit – Training Video

Location Kit – Documentation

Location Kit – Training Video

Site Kit