[Huawei Developers] Berk Özyurt:
Hello everyone.

In this article, I will talk about the Search Kit, which a new feature offered by Huawei to developers, and how to use it in android applications.

What is Search Kit?

Search Kit is one of Huawei’s latest released features. One of the most liked features of Huawei, which continues to improve itself day by day and offer new features to software developers, was the Search Kit.

Search Kit provides to you quickly and easily use a seamless mobile application search experience within the HMS ecosystem by using Petal Search APIs in the background.

HUAWEI Search Kit fully opens Petal Search capabilities through the device-side SDK and cloud-side APIs, enabling ecosystem partners to quickly provide the optimal mobile app search experience.

Search Kit provides to developers with 4 different types of searches. These are Web Search, News Search, Image Search and Video Search.

I am sure that Search Kit will attract all developers in a very short time, as it offers a fast application development experience, and its output is consistently and quickly and completely free.

Development Steps

1. Integration

First, a developer account must be created and HMS Core must be integrated into the project to use HMS. You can access the article about that steps from the link below.

2.Adding Dependencies

After HMS Core is integrated into the project and the Search Kit is activated through the console, the required library should added to the build.gradle file in the app directory as follows.

dependencies {
implementation 'com.huawei.hms:searchkit:5.0.4.303'
}

The project’s minSdkVersion value should be 24. For this, the minSdkVersion value in the same file should be updated to 24.

android {
...
defaultConfig {
...
minSdkVersion 24
...
}
...
}

3.Adding Permissions

The following line should be added to the AndroidManifest.xml file to allow HTTP requests. Absolutely, we shouldn’t forget to add internet permissions.

<application
...
android:usesCleartextTraffic="true"
>
...
</application>

4.Create Application Class

An Application class is required to launch the Search Kit when starting the application. Search Kit is launched in this class and it is provided to start with the project. Here, App Id must be given as parameter while initting Search Kit. After the BaseApplication class is created, it must be defined in the Manifest file.

class BaseApplication: Application() {

override fun onCreate() {
super.onCreate()

SearchKitInstance.init(this, Constants.APP_ID)
}
}

5.Search Screen

After all of the permissions and libraries have been added to the project, search operations can started. For this, a general search screen should be designed first. In its simplest form, adding a search box, 4 buttons to select the search type, and a recyclerView can create a simple and elegant search screen. For reference, I share the screen I created in the below.

Thanks to the design, you can list the 4 different search results type on the same page using different adapters.

<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"
tools:context=".ui.view.activity.SearchActivity">

<RelativeLayout
android:id="@+id/searchview_layout"
android:layout_height="36dp"
android:layout_width="match_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp">

<EditText
android:id="@+id/searchText"
android:layout_width="match_parent"
android:layout_height="36dp"
android:background="@drawable/search_box"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center_vertical|start"
android:hint="Search"
android:fontFamily="@font/muli_regular"
android:imeOptions="actionSearch"
android:paddingStart="42dp"
android:paddingEnd="40dp"
android:singleLine="true"
android:ellipsize="end"
android:maxEms="13"
android:textAlignment="viewStart"
android:textColor="#000000"
android:textColorHint="#61000000"
android:textCursorDrawable="@drawable/selected_search_box"
android:textSize="16sp" />

<ImageView
android:id="@+id/search_src_icon"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginStart="3dp"
android:clickable="false"
android:focusable="false"
android:padding="10dp"
android:src="@drawable/ic_search" />
</RelativeLayout>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="left"
android:layout_below="@+id/searchview_layout"
android:id="@+id/database_searchButtons"
android:layout_marginTop="25dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/search_box">
<TextView
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_weight="1"
android:gravity="center"
android:layout_marginLeft="20dp"
android:background="#e8e6e5"
android:id="@+id/btn_searchWeb"
android:text="Web"
android:textAllCaps="false"
android:textStyle="bold"
android:textColor="#000000"
android:fontFamily="@font/muli_regular"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_weight="1"
android:gravity="center"
android:background="#e8e6e5"
android:id="@+id/btn_searchNews"
android:text="News"
android:textAllCaps="false"
android:textStyle="bold"
android:textColor="#000000"
android:fontFamily="@font/muli_regular"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_weight="1"
android:gravity="center"
android:background="#e8e6e5"
android:id="@+id/btn_searchImage"
android:text="Image"
android:textAllCaps="false"
android:textStyle="bold"
android:textColor="#000000"
android:fontFamily="@font/muli_regular"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_weight="1"
android:gravity="center"
android:layout_marginRight="30dp"
android:background="#e8e6e5"
android:id="@+id/btn_searchVideo"
android:textAllCaps="false"
android:text="Video"
android:textStyle="bold"
android:textColor="#000000"
android:fontFamily="@font/muli_regular"/>

</LinearLayout>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_below="@+id/database_searchButtons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="15dp"
android:fontFamily="@font/muli_regular">

</androidx.recyclerview.widget.RecyclerView>

</RelativeLayout>

6.Create List Item and Adapters

A list item must be designed for the search results to listed in RecyclerView. For that, you can design as you wish and simply create adapter classes. For sample, you can see how the results are listed in my project in the next steps.

7.Web Search

To search on the web, a method should be created that taking the search word and access token values as parameters and returns the WebItem values as an array. WebItem is a kind of model class that comes automatically with the Search Kit library. In this way, the WebItem object can be used without the need to define another model class. In this method, firstly, an object must be created from WebSearchRequest() object and some parameters must be set. You can find a description of these values in the below.

webSearchRequest.setQ() -> Search text.
webSearchRequest.setLang() - > Search language.
webSearchRequest.setSregion() -> Search region.
webSearchRequest.setPs() -> Result number.
webSearchRequest.setPn() -> Page number.

After the values are set and the web search is started, the values can be set to the WebItem object and added to the list with a “for” loop and returned this list.

The Web Search method should be as following. In addition, as can be seen in the code, all values of the WebItem object are printed with the logs.

fun doWebSearch(searchText: String, accessToken: String) : ArrayList<WebItem>{
val webSearchRequest = WebSearchRequest()
webSearchRequest.setQ(searchText)
webSearchRequest.setLang(Language.ENGLISH)
webSearchRequest.setSregion(Region.UNITEDKINGDOM)
webSearchRequest.setPs(10)
webSearchRequest.setPn(1)
SearchKitInstance.getInstance().setInstanceCredential(accessToken)
val webSearchResponse = SearchKitInstance.getInstance().webSearcher.search(webSearchRequest)
for(i in webSearchResponse.getData()){
webResults.add(i)
Log.i(Constants.TAG_SEARCH_REPOSITORY, "site_name : " + i.site_name + "\n"
+ "getSnippet : " + i.getSnippet() + "\n"
+ "siteName : " + i.siteName + "\n"
+ "title : " + i.title + "\n"
+ "clickUrl : " + i.clickUrl + "\n"
+ "click_url : " + i.click_url + "\n"
+ "getTitle : " + i.getTitle())
}
return webResults
}

The results of the doWebSearch() method can be listed by transferring them to RecyclerView with the adapter. Yo can find a sample screenshot in the below.

8.News Search

To search on the news, a method should be created that taking the search word and access token values as parameters and returns the NewsItem values as an array. NewsItem is a kind of model class that comes automatically with the Search Kit library. In this way, the NewsItem object can be used without the need to define another model class. In this method, firstly, an object must be created from CommonSearchRequest() object and some parameters must be set. You can find a description of these values in the below.

commonSearchRequest.setQ() -> Search text.
commonSearchRequest.setLang() - > Search language.
commonSearchRequest.setSregion() -> Search region.
commonSearchRequest.setPs() -> Result number.
commonSearchRequest.setPn() -> Page number.

After the values are set and the news search is started, the values can be set to the NewsItem object and added to the list with a “for” loop and returned this list.

The News Search method should be as following. In addition, as can be seen in the code, all values of the NewsItem object are printed with the logs.

fun doNewsSearch(searchText: String, accessToken: String) : ArrayList<NewsItem>{
val commonSearchRequest = CommonSearchRequest()
commonSearchRequest.setQ(searchText)
commonSearchRequest.setLang(Language.ENGLISH)
commonSearchRequest.setSregion(Region.UNITEDKINGDOM)
commonSearchRequest.setPs(10)
commonSearchRequest.setPn(1)
SearchKitInstance.getInstance().setInstanceCredential(accessToken)
val newsSearchResponse = SearchKitInstance.getInstance().newsSearcher.search(commonSearchRequest)

for(i in newsSearchResponse.getData()) {
newsResults.add(i)
Log.i(
Constants.TAG_SEARCH_REPOSITORY,
"provider : " + i.provider + "\n"
+ "sourceImage.imageHostpageUrl : " + i.provider.logo + "\n"
+ "provider.logo : " + i.provider.siteName + "\n"
+ "provider.site_name : " + i.provider.site_name + "\n"
+ "provider.getLogo() : " + i.provider.getLogo() + "\n"
+ "publishTime : " + i.publishTime + "\n"
+ "getProvider() : " + i.getProvider() + "\n"
+ "getProvider().getLogo() : " + i.getProvider().getLogo() + "\n"
+ "getProvider().site_name : " + i.getProvider().site_name + "\n"
+ "getProvider().siteName : " + i.getProvider().siteName
)
Log.i(
Constants.TAG_SEARCH_REPOSITORY,
"getProvider().logo : " + i.getProvider().logo + "\n"
+ "publish_time : " + i.publish_time + "\n"
+ "getThumbnail() : " + i.getThumbnail() + "\n"
+ "click_url : " + i.click_url + "\n"
+ "thumbnail : " + i.thumbnail + "\n"
+ "getTitle(): " + i.getTitle() + "\n"
+ "title : " + i.title
)
}
return newsResults
}

The results of the doNewsSearch() method can be listed by transferring them to RecyclerView with the adapter. Yo can find a sample screenshot in the below.

9.Image Search

To search on the images, a method should be created that taking the search word and access token values as parameters and returns the ImageItem values as an array. ImageItem is a kind of model class that comes automatically with the Search Kit library. In this way, the ImageItem object can be used without the need to define another model class. In this method, firstly, an object must be created from CommonSearchRequest() object and some parameters must be set. You can find a description of these values in the below.

commonSearchRequest.setQ() -> Search text.
commonSearchRequest.setLang() - > Search language.
commonSearchRequest.setSregion() -> Search region.
commonSearchRequest.setPs() -> Result number.
commonSearchRequest.setPn() -> Page number.

After the values are set and the image search is started, the values can be set to the ImageItem object and added to the list with a “for” loop and returned this list.

The Image Search method should be as following. In addition, as can be seen in the code, all values of the ImageItem object are printed with the logs.

fun doImageSearch(searchText: String, accessToken: String) : ArrayList<ImageItem>{
val commonSearchRequest = CommonSearchRequest()
commonSearchRequest.setQ(searchText)
commonSearchRequest.setLang(Language.ENGLISH)
commonSearchRequest.setSregion(Region.UNITEDKINGDOM)
commonSearchRequest.setPs(10)
commonSearchRequest.setPn(1)
SearchKitInstance.getInstance().setInstanceCredential(accessToken)
val imageSearchResponse = SearchKitInstance.getInstance().imageSearcher.search(commonSearchRequest)
for(i in imageSearchResponse.getData()) {
imageResults.add(i)
Log.i(
Constants.TAG_SEARCH_REPOSITORY,
"IMAGE sourceImage.imageContentUrl : " + i.sourceImage.imageContentUrl + "\n"
+ "sourceImage.image_content_url : " + i.sourceImage.image_content_url + "\n"
+ "sourceImage.imageHostpageUrl : " + i.sourceImage.imageHostpageUrl + "\n"
+ "sourceImage.image_hostpage_url : " + i.sourceImage.image_hostpage_url + "\n"
+ "sourceImage.height : " + i.sourceImage.height + "\n"
+ "sourceImage.width : " + i.sourceImage.width + "\n"
+ "sourceImage.getHeight() : " + i.sourceImage.getHeight() + "\n"
+ "sourceImage.getWidth() : " + i.sourceImage.getWidth() + "\n"
+ "sourceImage.publishTime : " + i.sourceImage.publishTime + "\n"
+ "sourceImage.publish_time : " + i.sourceImage.publish_time + "\n"
+ "source_image : " + i.source_image + "\n"
+ "sourceImage : " + i.sourceImage
)
Log.i(
Constants.TAG_SEARCH_REPOSITORY, "title : " + i.title + "\n"
+ "getTitle() : " + i.getTitle() + "\n"
+ "thumbnail : " + i.thumbnail + "\n"
+ "click_url : " + i.click_url + "\n"
+ "clickUrl : " + i.clickUrl + "\n"
+ "getThumbnail() : " + i.getThumbnail()
)
}
return imageResults
}

The results of the doImageSearch() method can be listed by transferring them to RecyclerView with the adapter. Yo can find a sample screenshot in the below.

10.Video Search

To search on the videos, a method should be created that taking the search word and access token values as parameters and returns the VideoItem values as an array. VideoItem is a kind of model class that comes automatically with the Search Kit library. In this way, the VideoItem object can be used without the need to define another model class. In this method, firstly, an object must be created from CommonSearchRequest() object and some parameters must be set. You can find a description of these values in the below.

commonSearchRequest.setQ() -> Search text.
commonSearchRequest.setLang() - > Search language.
commonSearchRequest.setSregion() -> Search region.
commonSearchRequest.setPs() -> Result number.
commonSearchRequest.setPn() -> Page number.

After the values are set and the video search is started, the values can be set to the VideoItem object and added to the list with a “for” loop and returned this list.

The Video Search method should be as following. In addition, as can be seen in the code, all values of the VideoItem object are printed with the logs.

fun doVideoSearch(searchText: String, accessToken: String) : ArrayList<VideoItem>{
val commonSearchRequest = CommonSearchRequest()
commonSearchRequest.setQ(searchText)
commonSearchRequest.setLang(Language.ENGLISH)
commonSearchRequest.setSregion(Region.UNITEDKINGDOM)
commonSearchRequest.setPs(10)
commonSearchRequest.setPn(1)
SearchKitInstance.getInstance().setInstanceCredential(accessToken)
val videoSearchResponse = SearchKitInstance.getInstance().videoSearcher.search(commonSearchRequest)

for(i in videoSearchResponse.getData()) {
videoResults.add(i)
Log.i(
Constants.TAG_SEARCH_REPOSITORY,
"getDuration() : " + i.getDuration() + "\n"
+ "provider : " + i.provider + "\n"
+ "sourceImage.imageHostpageUrl : " + i.provider.logo + "\n"
+ "provider.logo : " + i.provider.siteName + "\n"
+ "provider.site_name : " + i.provider.site_name + "\n"
+ "provider.getLogo() : " + i.provider.getLogo() + "\n"
+ "duration : " + i.duration + "\n"
+ "publishTime : " + i.publishTime + "\n"
+ "getProvider() : " + i.getProvider() + "\n"
+ "getProvider().getLogo() : " + i.getProvider().getLogo() + "\n"
+ "getProvider().site_name : " + i.getProvider().site_name + "\n"
+ "getProvider().siteName : " + i.getProvider().siteName
)
Log.i(
Constants.TAG_SEARCH_REPOSITORY,
"getProvider().logo : " + i.getProvider().logo + "\n"
+ "publish_time : " + i.publish_time + "\n"
+ "getThumbnail() : " + i.getThumbnail() + "\n"
+ "click_url : " + i.click_url + "\n"
+ "thumbnail : " + i.thumbnail + "\n"
+ "getTitle(): " + i.getTitle() + "\n"
+ "title : " + i.title
)
}
return videoResults
}

The results of the doVideoSearch() method can be listed by transferring them to RecyclerView with the adapter. Yo can find a sample screenshot in the below.

11.Detail Pages

After the search results are transferred to RecyclerView, one page can be designed, directed by the “Detail >>” button to view the details. You can also get help from your adapter class to transfer the result of the item you selected to the page you designed. For an example, you can examine the detail pages I have created in the below. On the detail pages, you can open the relevant links, view the images and videos etc.