Get Places with using Huawei — HMS Site Kit

Mine KULAÇ AKKULAK
Huawei Developers
Published in
5 min readMar 30, 2020

Hi everyone,

In this tutorial, I will guide you how to get nearby cinema places and text search a place with using HMS Site Kit. And, we will show them on RecyclerView.

Before the coding, let’s integrate the Site Kit and Location Kit to the project with these instructions; Site Kit, Location Kit.

Site Kit Nearby Search

To get nearby places, we need to know current location. So, we will get the location information with using HMS Location Kit.

private fun getLocation(){

fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

val mLocationCallback: LocationCallback = object : LocationCallback(){
override fun onLocationResult(locationResult: LocationResult) {
currentLatitude = locationResult.lastLocation.latitude
currentLongitude = locationResult.lastLocation.longitude
}
}

val mLocationRequest = LocationRequest()
mLocationRequest.interval = 1800000 // change the interval as needed
mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY

fusedLocationProviderClient.requestLocationUpdates(mLocationRequest,mLocationCallback,
Looper.getMainLooper()).addOnSuccessListener{}.addOnFailureListener{}

}

Now, we know our current location. Let’s try to get nearby cinema places. Site Kit has NearbySearchRequest class. We need to use this request class. Related parameters are as follows,

public class NearbySearchRequest {
private Integer pageSize;
private Integer pageIndex;
private String query;
private Coordinate location;
private Integer radius;
private LocationType poiType;
private String language;
}

At this tutorial, we will use these parameters: LocationType.MOVIE_THEATER as poiTypes, location, radius and pageIndex.

First, let’s create a request object with parameters. we will request for cinemas which are closest to our location, within 6000m.

val request = NearbySearchRequest()
request.poiType = LocationType.MOVIE_THEATER
request.location = Coordinate(currentLatitude, currentLongitude)
request.radius = 6000 // meter
request.pageIndex = 1

For Api connection, Site Kit has SearchService interface. To get nearby places, we need to use nearbySearch(NearbySearchRequest request,

SearchResultListener<NearbySearchResponse> listener) method with adding request object and result listener.

lateinit var siteCinemaList: List<Site>val searchService = SearchServiceFactory.create(context)
searchService.nearbySearch(request, object : SearchResultListener<NearbySearchResponse>{
override fun onSearchError(status: SearchStatus?) {
Log.e("onSearchError", status.errorMessage)
}

override fun onSearchResult(response: NearbySearchResponse?) {
response?.let {
siteCinemaList = it.sites
setCinemaRecyclerView(siteCinemaList)
}
}
})

NearbySearchResponse data structure:

public class NearbySearchResponse {
private List<Site> sites;
private int totalCount;
}
public class Site {
private String siteId;
private String name;
private String formatAddress;
private AddressDetail address;
private Coordinate location;
private CoordinateBounds viewport;
private double distance;
private Poi poi;
}

From onSearchResult method, we got the cinemas closest to our location within 6000 m. Now, we are ready to show cinemas at RecyclerView.

Let’s create item layout; place_cinema_view_holder

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
card_view:cardCornerRadius="10dp"
card_view:cardElevation="10dp"
card_view:cardBackgroundColor="@color/colorPrimary">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">

<TextView
android:id="@+id/cinemaName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="@android:color/white"
android:textStyle="italic"/>

<TextView
android:id="@+id/cinemaAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:textColor="@color/white_90"/>

<TextView
android:id="@+id/cinemaDistance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:textColor="@color/forest_green"/>

<TextView
android:id="@+id/cinemaOpeningHour"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:textColor="@color/white_90"/>

<TextView
android:id="@+id/cinemaPhoneNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:textColor="@color/white_90"/>

<TextView
android:id="@+id/cinemaWebsiteUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:textColor="@color/white_90"/>

</LinearLayout>

</androidx.cardview.widget.CardView>

Let’s create ViewHolder related with our layout

class CinemaViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val cinemaName: TextView = view.findViewById(R.id.cinemaName)
val cinemaAddress: TextView = view.findViewById(R.id.cinemaAddress)
val cinemaDistance: TextView = view.findViewById(R.id.cinemaDistance)
val cinemaOpeningHour: TextView = view.findViewById(R.id.cinemaOpeningHour)
val cinemaPhoneNumber: TextView = view.findViewById(R.id.cinemaPhoneNumber)
val cinemaWebsiteUrl: TextView = view.findViewById(R.id.cinemaWebsiteUrl)
}

At RecyclerView Adapter, we need to inflate layout we created above at onCreateViewHolder

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view: View = inflater.inflate(R.layout.place_cinema_view_holder, parent, false)
return PlaceCinemaViewHolder(view)
}

Let’s set the cinema information (we get from Site Kit NearbySearch) to the holder item at onBindViewHolder

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val cinemaViewHolder = holder as CinemaViewHolder
val cinema: Site? = getItem(position)
if(cinema!=null){
cinemaViewHolder.cinemaName.text = cinema.name
cinemaViewHolder.cinemaAddress.text = cinema.formatAddress
cinemaViewHolder.cinemaDistance.text =
calculateDistanceFromLocation(cinema.location.lat,cinema.location.lng)
cinemaViewHolder.placeOpeningHour.text =
context.getString(R.string.place_opening_hour,cinema.poi.openingHours.texts[0])
cinemaViewHolder.placePhoneNumber.text =
context.getString(R.string.place_phone_number,cinema.poi.phone)
cinemaViewHolder.placeWebsiteUrl.text =
context.getString(R.string.place_website,cinema.poi.websiteUrl)
}
}
<string name="place_opening_hour">Hour : %s</string>
<string name="place_phone_number">Phone : %s</string>
<string name="place_website">Website : %s</string>
<string name="distance_km">km</string>

To show distance between current and cinema location, we can use this helper method:

private fun calculateDistanceFromLocation(pLatitude : Double, pLongitude : Double) : String{
val locationA = Location("point A")

locationA.latitude = latitude
locationA.longitude = longitude

val locationB = Location("point B")

locationB.latitude = pLatitude
locationB.longitude = pLongitude

val distance: Float = locationA.distanceTo(locationB)
return formatDistance(distance.toInt())
}

private fun formatDistance(distance : Int?) =
when {
distance!! > 1000 -> String.format("%.1f", distance / 1000.0) + " " +
context.getString(R.string.distance_km)
else -> "$distance " + context.getString(R.string.distance_m)
}

Finally, we need to set the RecyclerView at our activity or fragment

fun setCinemaRecyclerView(){
cinemaAdapter = CinemaAdapter(siteCinemaList)
cinemaRecyclerView.adapter = placeCinemaAdapter
}

Site Kit Text Search

Above, we tried to get nearby cinemas. Now we will try to get cinema list from a ”query text”.

To search with a text, Site Kit has TextSearchRequest class. We need to use this request class. Related parameters are as follows

public class TextSearchRequest {
private String language;
private String query;
private Coordinate location;
private Integer radius;
private CoordinateBounds bounds;
private Integer pageSize;
private LocationType poiType;
private Integer pageIndex;
private String countryCode;
}

Now, we will use these parameters: LocationType.MOVIE_THEATER as poiTypes, location, radius, pageIndex, pagesize and query.

Let’s create a request object with parameters.

val request = TextSearchRequest()
request.query = “Cinemaximum”
request.poiType = LocationType.MOVIE_THEATER
request.location = Coordinate(currentLatitude, currentLongitude)
request.radius = 10000 //meter
request.pageIndex = 1
request.pageSize = 20

With this request, we will try to get cinemas with the name “Cinemaximum” between our location and 10000 m.

With SearchService interface (I explained above), now we need to use

textSearch (TextSearchRequest request, SearchResultListener<TextSearchResponse> listener) method with adding request object and result listener.

searchService.textSearch(request, object :SearchResultListener<TextSearchResponse>{
override fun onSearchError(status: SearchStatus?) {
Log.e("onSearchError", status.errorMessage)
}

override fun onSearchResult(response: TextSearchResponse?) {
response?.let {
siteCinemaList = it.sites
setCinemaRecyclerView(siteCinemaList)
}
}
})

TextSearchResponse data structure:

public class TextSearchResponse {
private int totalCount;
private List<Site> sites;
}
public class Site {
private String siteId;
private String name;
private String formatAddress;
private AddressDetail address;
private Coordinate location;
private CoordinateBounds viewport;
private double distance;
private Poi poi;
}

From onSearchResult method, we got the cinemas with the name “Cinemaximum” between our location and 10000 m. Now, we are ready to show cinemas at RecyclerView. You can follow instruction I explained above to show the cinemas at RecyclerView.

I hope, you found this tutorial helpful and if you have any comments or questions, please let me know in the comments below.

--

--