Get Places with using Huawei — HMS Site Kit
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.