[Huawei Developers] Freemind R:
The Huawei Search Kit provide awesome capabilities to build your own search engine or even go beyond. With Search Kit you can add a mini web browser to your app app with web searching capabilities, by this way, the user will be able to surf into the Internet without knowing the complete URL of the website. In this article we will build a Web Browser application powered by Search Kit.

Previous Requirements

A verified developer account

A configured project in AppGallery Connect

Configuring and adding the Search Kit

Once you have propely configured you project in AGC, go to "Manage APIs" from your project settings and enable Search Kit.

Note: Search Kit require to choose a Data Storage Location, make sure to choose a DSL which support the countries where you plan to release your app.

Once you have enabled the API and choosen the Data Storage Location, download (or re-download) you agconnect-services.json and add it to your Android Project. Then, add the Serach Kit latest dependency to your app-level build.gradle file, we will also need the related dependencies of coroutines and data binding.

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation 'com.huawei.agconnect:agconnect-core:1.4.2.301'
implementation 'com.huawei.hms:searchkit:5.0.4.303'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'

Initializing the SDK

Before using Search Kit, you must apply for an access token, in order to authenticate the requests yo made by using the kit. If you don't provide the proper credentials, Search Kit will not work.

To get your Access Token, perform the next POST request:

Endpoint:

https://oauth-login.cloud.huawei.com/oauth2/v3/token

Headers:

content-type: application/x-www-form-urlencoded

Body:

"grant_type=client_credentials&client_secret=APP_SECRET&client_id=APP_ID"

Your App Id and App Secret will be available from your App dashboard in AGC

Note: Before sending the request, you must encode your AppSecret with URLEncode.

In order to perform the token request, let's create a request helper

HTTPHelper.kt

object HTTPHelper {
fun sendHttpRequest(
url: URL,
method: String,
headers: HashMap<String, String>,
body: ByteArray
): String {
val conn = url.openConnection() as HttpURLConnection
conn.apply {
requestMethod = method
doOutput = true
doInput = true
for (key in headers.keys) {
setRequestProperty(key, headers[key])
}
if(method!="GET"){
outputStream.write(body)
outputStream.flush()
}
}
val inputStream = if (conn.responseCode < 400) {
conn.inputStream
} else conn.errorStream
return convertStreamToString(inputStream).also { conn.disconnect() }
}

private fun convertStreamToString(input: InputStream): String {
return BufferedReader(InputStreamReader(input)).use {
val response = StringBuffer()
var inputLine = it.readLine()
while (inputLine != null) {
response.append(inputLine)
inputLine = it.readLine()
}
it.close()
response.toString()
}
}
}

We will take advantage of the Kotlin Extensions to add the token request to the SearchKitInstance class, if we initialize the Search Kit from the Application Class, a fresh token will be obtained upon each app startup. When you have retrieved the token, call the method SearchKitInstance.getInstance().setInstanceCredential(token)

BrowserApplication.kt

class BrowserApplication : Application() {

companion object {
const val TOKEN_URL = "https://oauth-login.cloud.huawei.com/oauth2/v3/token"
const val APP_SECRET = "YOUR_OWN_APP_SECRET"
}

override fun onCreate() {
super.onCreate()
val appID = AGConnectServicesConfig
.fromContext(this)
.getString("client/app_id")
SearchKitInstance.init(this, appID)
CoroutineScope(Dispatchers.IO).launch {
SearchKitInstance.instance.refreshToken(this@BrowserApplication)
}
}

}

fun SearchKitInstance.refreshToken(context: Context) {
val config = AGConnectServicesConfig.fromContext(context)
val appId = config.getString("client/app_id")
val url = URL(BrowserApplication.TOKEN_URL)
val headers = HashMap<String, String>().apply {
put("content-type", "application/x-www-form-urlencoded")
}
val msgBody = MessageFormat.format(
"grant_type={0}&client_secret={1}&client_id={2}",
"client_credentials", URLEncoder.encode(APP_SECRET, "UTF-8"), appId
).toByteArray(Charsets.UTF_8)

val response = HTTPHelper.sendHttpRequest(url, "POST", headers, msgBody)
Log.e("token", response)
val accessToken = JSONObject(response).let {
if (it.has("access_token")) {
it.getString("access_token")
} else ""
}
setInstanceCredential(accessToken)

}

In short words, the basic setup of Search Kit is as follows:

Init the service, by calling SearchKitInstance.init(Context, appID)

Rerieve an App-Level access token

Call SearchKitInstance.getInstance().setInstanceCredential(token) to specify the access token which Search Kit will use to authenticate the requests

Auto Complete Widget

Let's create a custom widget wich can be added to any Activity or Fragment, this widget will show some search suggestions to the user when begins to write in the search bar.

First, we must design the Search Bar, it will contain an Image View and an Edit Text.

view_search.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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="wrap_content"
android:background="@drawable/gray_rec"
android:paddingHorizontal="5dp"
android:paddingVertical="5dp"
>

<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_menu_search"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/ic_menu_search" />

<EditText
android:id="@+id/textSearch"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="parent"
/>

</androidx.constraintlayout.widget.ConstraintLayout>

Now is time to create the widget layout, it will contain our search bar and a recycler view to show the suggestions

More details, you can check https://forums.developer.huawei.com/forumPortal/en/topic/0202455305475510024