⚠️ 本文記錄的是 Dialogflow 在 Android 上的測試性串接,並非官方支援或建議做法。若需穩定實作,建議改採 REST API 或透過後端 Proxy 呼叫。
最近因為專案上的需求,需要在 Android 端上實作一個簡易的聊天機器人,而後端使用的技術是 Dialogflow API。爬了一堆文之後,卻發現 Android 端的實作說明不多,甚至連官方文件都爬不太到,因此整理一個目前測試下來可以運作的方式。
實作的內容主要參考自 Medium: Android chatbot with Dialogflow 與 Github: DialogflowChat。
本文章主要會說明 Android 端如何串接與實作,
Dialogflow 的專案建置可以參考
這篇 【技術文章】DialogFlow輕鬆建立屬於你的聊天機器人!
我覺得寫的滿清楚的~
實作 (簡易對話)#
一、環境建置#
app’s build.gradle
#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| android {
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/INDEX.LIST'
}
}
dependencies {
// Java V2
implementation 'com.google.cloud:google-cloud-dialogflow:2.2.0'
// for Remote Procedure Call to avoid
// "No functional channel service provider found" error
// while creating SessionsClient
implementation 'io.grpc:grpc-okhttp:1.31.1'
}
|
二、初始化#
將從後台下載拿到的 JSON 檔放到任意路徑,我是將它放在 assets
資料夾中再讀進來。
那份 JSON 結構應該會是長這樣,
1
2
3
4
5
6
7
8
9
10
11
12
| {
"type": "",
"project_id": "",
"private_key_id": "",
"private_key": "",
"client_email": "",
"client_id": "",
"auth_uri": "",
"token_uri": "",
"auth_provider_x509_cert_url": "",
"client_x509_cert_url": ""
}
|
使用憑證初始化,並建立一個 Session#
Session 僅用來識別對話,它不代表連線成功,實際的對話還是要等你送出訊息後才開始。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| private var sessionClient: SessionsClient? = null
private var session: SessionName? = null
private val uuid = UUID.randomUUID().toString()
fun initChatBot(inputStream: InputStream) {
try {
val credentials = GoogleCredentials.fromStream(inputStream) as ServiceAccountCredentials
val projectId = credentials.projectId
val sessionSettings = SessionsSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(credentials))
.build()
sessionClient = SessionsClient.create(sessionSettings)
session = SessionName.of(projectId, uuid)
} catch (e: Exception) {
Log.e(TAG, "init: ", e)
}
}
|
三、發送訊息#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| suspend fun sendMessage(input: String): DetectIntentResponse? {
return withContext(Dispatchers.IO) {
try {
val textInput =
TextInput.newBuilder().setText(input).setLanguageCode("zh-tw").build()
val queryInput =
QueryInput.newBuilder()
.setText(textInput)
.build()
val detectIntentRequest =
DetectIntentRequest.newBuilder()
.setSession(session.toString())
.setQueryInput(queryInput)
.build()
sessionClient?.detectIntent(detectIntentRequest)
} catch (e: Exception) {
Log.e(TAG, "sendMessage: ", e)
null
}
}
}
|
TextInput
: 純文字輸入。QueryInput
: 可以是語音,也可以是純文字。DetectIntentResponse
: 回傳訊息。
四、接收訊息#
1
2
3
4
5
| val response = sessionClient?.detectIntent(detectIntentRequest)
response?.let {
val reply = it.queryResult.fulfillmentText
Log.d(TAG, "sendMessage: $reply")
}
|
外部連結#
Medium/ iThome#
Github#
Doc#