[Huawei Developers] XDARoni:
The HMS Site Kit SDK is a handy set of APIs to help you implement location and address-based searching in your app with ease. If you want to target Huawei devices with your app, and you're looking for a simple way to find and show results to your user, you've come to the right place.

This guide will get you started with the Site Kit SDK, and give you some basic implementation examples. Let's get started.

Preparation

First up, make sure you have a Huawei Developer Account. This process can take a couple days, and you'll need one to use this SDK, so be sure to start that as soon as possible. You can sign up at https://developer.huawei.com.

Next, you'll want to obtain the SHA-256 representation of your app's signing key. If you don't have a signing key yet, be sure to create one before continuing. To obtain your signing key's SHA-256, you'll need to use Keytool which is part of the JDK installation. Keytool is a command-line program. If you're on Windows, open CMD. If you're on Linux, open Terminal.

On Windows, you'll need to "cd" into the directory containing the Keytool executable. For example, if you have JDK 1.8 v231 installed, Keytool will be located at the following path:

C:\Program Files\Java\jdk1.8.0_231\bin\

Once you find the directory, "cd" into it:

C: #Make sure you're in the right drive
cd C:\Program Files\Java\jdk1.8.0_231\bin\

Next, you need to find the location of your keystore. Using Android's debug keystore as an example, where the Android SDK is hosted on the "E:" drive in Windows, the path will be as follows:

E:\AndroidSDK\.android\debug.keystore

(Keytool also supports JKS-format keystores.)

Now you're ready to run the command. On Windows, it'll look something like this:

keytool -list -v -keystore E:\AndroidSDK\.android\debug.keystore

On Linux, the command should be similar, just using UNIX-style paths instead.

Enter the keystore password, and the key name (if applicable), and you'll be presented with something similar to the following:

Make note of the SHA256 field.

SDK Setup

Now we're ready to add the Site Kit SDK to your Android Studio project. Go to your Huawei Developer Console and click the HUAWEI AppGallery tile. Agree to the terms of use if prompted.

Click the "My projects" tile here. If you haven't already added your project to the AppGallery, add it now. You'll be asked for a project name. Make it something descriptive so you know what it's for.

Now, you should be on a screen that looks something like the following:

Click the "Add app" button. Here, you'll need to provide some details about your app, like its name and package name.

Once you click OK, some SDK setup instructions will be displayed. Follow them to get everything added to your project. You'll also need to add the following to the "dependencies" section of your app-level build.gradle file:

implementation 'com.huawei.hms:site:5.0.0.300'

If you ever need to come back to these instructions, you can always click the "Add SDK" button after "App information" on the "Project setting" page.

Now you should be back on the "Project setting" page. Find the "SHA-256 certificate fingerprint" field under "App information," click the "+" button, and paste your SHA-256.

Now, go to the Manage APIs tab on the "Project setting" page. Scroll down until you find "Site Kit" and make sure it's enabled.

Now, if you're using obfuscation in your app, you'll need to whitelist a few things for HMS to work properly.

For ProGuard:

-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}

For AndResGuard:

"R.string.hms*",
"R.string.agc*",
"R.string.connect_server_fail_prompt_toast",
"R.string.getting_message_fail_prompt_toast",
"R.string.no_available_network_prompt_toast",
"R.string.third_app_*",
"R.string.upsdk_*",
"R.layout.hms*",
"R.layout.upsdk_*",
"R.drawable.upsdk*",
"R.color.upsdk*",
"R.dimen.upsdk*",
"R.style.upsdk*"

That's it! The Site Kit SDK should now be available in your project.

Basic Usage

Huawei's Site Kit SDK gives you quite a few useful features.

There's Keyword Search, which lets the user type in a search query, along with other options, and see relevant results.

There's Nearby Place Search, which returns points of interest close to the user. There's a Place Details API, to let the user find out more about a specific place.

There's the Place Search Suggestion feature, which adds autofill-like search suggestions in real-time.

And finally, there's the Widget component, which implements Place Search Suggestion in a search bar for you.

We'll go over each feature one by one.

Keyword Search

Below is an example of how you might implement a keyword search.

//Create the search service. It's recommended you use an Activity
//Context, although it's not required.
//You can find your API key on the Project Setting page for your
//project in AppGallery Connect, under App Information.
val searchService = SearchServiceFactory.create(context, "API_KEY")

//Create a request. For this example, we're going to be
//using dummy inputs, but in a real app, these would
//be provided by the user.
val request = TextSearchRequest()

//This can be any keyword, like "McDonald's" or
//"Washington".
request.setQuery("London")

//Define a location (optional). This could be the user's
//current location, or some other area.
val location = Coordinate(48.893478, 2.334595)
request.setLocation(location)

//Set a radius in meters (optional). The default is 50,000.
location.setRadius(1000)

//Set the type of location (optional, but recommended).
//Values can be found in the HwLocationType class.
request.setHwPoiType(HwLocationType.ENTERTAINMENT_PLACE)

//Set the country code to where these results should be
//confined (optional). Uses the ISO-3166-1 alpha-2 standard.
request.setCountryCode("FR")

//Set the language for results to appear in (optional).
request.setLanguage("fr")

//Set the current page (from 1-60). Default is 1.
request.setPageIndex(1)

//Set how many results should appear per-page (from 1-20).
//Default is 20.
request.setPageSize(5)

//Create a result listener for handling search results.
val resultListener = object : SearchResultListener<TextSearchResponse>() {
override fun onSearchResult(result: TextSearchResponse?) {
//We've got results.

if (result == null || result.totalCount <= 0) {
//We actually don't have results. Return.
return
}

val sites: List<Site>? = result.sites
if (sites.isNullOrEmpty()) {
//Couldn't find any sites. Return.
return
}

//Handle results.
sites.forEach { site ->
val id = site.siteId
val name = site.name
}
}

override fun onSearchError(state: SearchStatus) {
//There was an error retrieving results.
val code = status.errorCode
val message = status.errorMessage
}
}

//Finally, initiate the search.
searchService.textSearch(request, resultListener)

Nearby Place Search

A Nearby Place Search is practically identical to a Keyword Search in terms of implementation. Simply replace the textSearch() call with a nearbySearch() call. Almost everything else is identical.

//Use this instead of `textSearch()`.
//One notable difference is that the default radius
//for a nearby search is 1,000 meters instead of 50,000.
searchService.nearbySearch(request, resultListener)

Place Details

Creating a Place Details request is similar to the previous two, although there are some differences in implementation. For one, you should know the site ID of the place whose details you're querying, which you can get using one of the above methods.

/Create the search service. It's recommended you use an Activity
//Context, although it's not required.
//You can find your API key on the Project Setting page for your
//project in AppGallery Connect, under App Information.
val searchService = SearchServiceFactory.create(context, "API_KEY")

//Create the details request.
val request = DetailSearchRequest()

//Set the site ID. You can retrieve this from a keyword or
//nearby place search result.
request.setSiteId("THE_SIDE_ID")

//Set the language (optional).
request.setLanguage("fr")

//Create a results listener.
val resultListener = object : SearchResultListener<DetailSearchResponse>() {
override fun onSearchResult(result: DetailSearchResponse?) {
//Detail search succeeded.

if (result == null) {
//Something weird happened. Return.
return
}

//Retrieve the site. Return if null.
val site = result.site ?: return

//Retrieve various details about the site and display
//for the user.
}

override fun onSearchError(status: SearchStatus) {
//There was an error retrieving results.
val code = status.errorCode
val message = status.errorMessage
}
}

//Initiate the request.
searchService.detailSearch(request, resultListener)

Place Search Suggestion

This feature is similar to the Keyword and Nearby Search features, except that it returns a limited set of results. It's more suitable for rapid-fire requests, such as real-time search suggestions.

Here's an example for how to implement it.

/Create the search service. It's recommended you use an Activity
//Context, although it's not required.
//You can find your API key on the Project Setting page for your
//project in AppGallery Connect, under App Information.
val searchService = SearchServiceFactory.create(context, "API_KEY")

//Create the request.
val request = QuerySuggestionRequest()

//Set the user's current query.
request.setQuery("Pari")

//Set a location (optional).
val location = Coordinate(48.893478, 2.334595)
request.setLocation(location)

//Set a radius in meters (optional) (from 1-50,000).
//Default is 50,000.
request.setRadius(50)

//Set the search country (optional).
request.setCountryCode("FR")

//Set the language results should appear in
//(optional).
request.setLanguage("fr")

//Set a specific POI type (optional). Should
//be a subset of the values found in LocationType.
request.setPoiTypes(LocationType.ADDRESS)

//Create a results listener.
val resultListener = object : SearchResultListener<QuerySuggestionResponse>() {
override fun onSearchResult(result: QuerySuggestionResponse?) {
if (result == null) {
//No results. Return.
return
}

val sites: List<Site>? = result.sites
if (sites.isNullOrEmpty()) {
//No sites. Return.
return
}

//Handle results.
sites.forEach { site ->
val id = site.sideId
val name = site.name
}
}

override fun onSearchError(status: SearchStatus) {
//There was an error retrieving results.
val code = status.errorCode
val message = status.errorMessage
}
}

//Initiate the search request.
searchServie.querySuggestion(request, resultListener)

Widget

The Site Kit can take care of search logic for you, including suggestions. Here's how.

The first thing you need to do is implement the Fragment in your layout.

<fragment
android:id="@+id/search_fragment"
android_name="com.huawei.hms.site.widget.SearchFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>

You can also create a reference in code and use a FragmentManager to add and remove it as needed.

Next, you need to implement the search functionality.

//Get a reference to the Fragment. This example assumes it's
//in your layout XML.
val searchFragment = supportFragmentManager.findFragmentById(R.id.search_fragment) as SearchFragment

//Set the API key.
//You can find your API key on the Project Setting page for your
//project in AppGallery Connect, under App Information.
searchFragment.setApiKey("API_KEY")

//Set a selection listener.
searchFragment.setOnSiteSelectedListener(object : SiteSelectionListener() {
override fun onSiteSelected(site: Site) {
//The user has selected a site returned by HMS.
//Handle as applicable.
}

override fun onError(status: SearchStatus) {
//There was an error retrieving results.
val code = status.errorCode
val message = status.errorMessage
}
})

Conclusion

That's it! As you can probably see, HMS Site Kit makes it pretty easy to implement location searching in your app.

This is only for devices that come with HMS pre-installed, but it's certainly a useful set of tools. Be sure to check out Huawei's full documentation for more details.