From 9a8b30f0c06fd1073f2a66acb775351e2e6aed4d Mon Sep 17 00:00:00 2001 From: doomsdayrs Date: Sat, 6 Nov 2021 00:38:52 -0400 Subject: [PATCH] Use kotlinx serialization instead of manual json encode/decode While this might have some extremely minor losses in performance, it makes up for this fact by making it far more easy to work with. I also placed them into their own directories to clean up the codebase. --- mobile/build.gradle.kts | 4 ++ .../src/main/java/mycroft/ai/MainActivity.kt | 14 ++++-- .../src/main/java/mycroft/ai/MessageParser.kt | 44 ++++++++++--------- .../java/mycroft/ai/entity/JSONMessage.kt | 31 +++++++++++++ .../java/mycroft/ai/entity/JSONMessageData.kt | 28 ++++++++++++ .../java/mycroft/ai/entity/JSONSendMessage.kt | 30 +++++++++++++ .../mycroft/ai/entity/JSONSendMessageData.kt | 28 ++++++++++++ 7 files changed, 154 insertions(+), 25 deletions(-) create mode 100644 mobile/src/main/java/mycroft/ai/entity/JSONMessage.kt create mode 100644 mobile/src/main/java/mycroft/ai/entity/JSONMessageData.kt create mode 100644 mobile/src/main/java/mycroft/ai/entity/JSONSendMessage.kt create mode 100644 mobile/src/main/java/mycroft/ai/entity/JSONSendMessageData.kt diff --git a/mobile/build.gradle.kts b/mobile/build.gradle.kts index 7eb18d46..277d9dfa 100755 --- a/mobile/build.gradle.kts +++ b/mobile/build.gradle.kts @@ -23,6 +23,7 @@ plugins { id("com.google.firebase.crashlytics") kotlin("android") id("com.google.gms.google-services") + kotlin("plugin.serialization") } android { @@ -96,4 +97,7 @@ dependencies { implementation("org.java-websocket:Java-WebSocket:1.5.2") implementation("androidx.legacy:legacy-support-core-utils:1.0.0") + + // kotlinx + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0") } diff --git a/mobile/src/main/java/mycroft/ai/MainActivity.kt b/mobile/src/main/java/mycroft/ai/MainActivity.kt index a6798aed..056dfd1f 100644 --- a/mobile/src/main/java/mycroft/ai/MainActivity.kt +++ b/mobile/src/main/java/mycroft/ai/MainActivity.kt @@ -38,10 +38,14 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.recyclerview.widget.LinearLayoutManager +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import mycroft.ai.Constants.MycroftMobileConstants.VERSION_CODE_PREFERENCE_KEY import mycroft.ai.Constants.MycroftMobileConstants.VERSION_NAME_PREFERENCE_KEY import mycroft.ai.adapters.MycroftAdapter import mycroft.ai.databinding.ActivityMainBinding +import mycroft.ai.entity.JSONSendMessage +import mycroft.ai.entity.JSONSendMessageData import mycroft.ai.receivers.NetworkChangeReceiver import mycroft.ai.shared.utilities.GuiUtilities import mycroft.ai.shared.wear.Constants.MycroftSharedConstants.MYCROFT_WEAR_REQUEST @@ -339,9 +343,11 @@ class MainActivity : AppCompatActivity() { } fun sendMessage(msg: String) { - val json = - "{\"data\": {\"utterances\": [\"$msg\"]}, \"type\": \"recognizer_loop:utterance\", \"context\": null}" - + val json = JSONSendMessage( + JSONSendMessageData(listOf(msg)), + "recognizer_loop:utterance", + null + ) try { if (webSocketClient == null || webSocketClient!!.connection.isClosed) { // try and reconnect @@ -354,7 +360,7 @@ class MainActivity : AppCompatActivity() { handler.postDelayed({ // Actions to do after 1 seconds try { - webSocketClient!!.send(json) + webSocketClient!!.send(Json.encodeToString(json)) addData(Utterance(msg, UtteranceFrom.USER)) } catch (exception: WebsocketNotConnectedException) { showToast(resources.getString(R.string.websocket_closed)) diff --git a/mobile/src/main/java/mycroft/ai/MessageParser.kt b/mobile/src/main/java/mycroft/ai/MessageParser.kt index f8825147..09324c1b 100755 --- a/mobile/src/main/java/mycroft/ai/MessageParser.kt +++ b/mobile/src/main/java/mycroft/ai/MessageParser.kt @@ -21,12 +21,13 @@ package mycroft.ai import android.util.Log - -import org.json.JSONException -import org.json.JSONObject +import kotlinx.serialization.SerializationException +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json +import mycroft.ai.entity.JSONMessage /** - * Specialised Runnable that parses the [JSONObject] in [.message] + * Specialised Runnable that parses the JSONObject in [.message] * when run. If it contains a [Utterance] object, the callback * defined in [the constructor][.MessageParser] will * be [called][SafeCallback.call] with that object as a parameter. @@ -37,22 +38,23 @@ import org.json.JSONObject * * @author Philip Cohn-Cort */ -internal class MessageParser(private val message: String, - private val callback: SafeCallback) : Runnable { - private val logTag = "MessageParser" +internal class MessageParser( + private val message: String, + private val callback: SafeCallback +) : Runnable { + private val logTag = "MessageParser" - override fun run() { - Log.i(logTag, message) - // new format - // {"data": {"utterance": "There are only two hard problems in Computer Science: cache invalidation, naming things and off-by-one-errors."}, "type": "speak", "context": null} - try { - val obj = JSONObject(message) - if (obj.optString("type") == "speak") { - val ret = Utterance(obj.getJSONObject("data").getString("utterance"), UtteranceFrom.MYCROFT) - callback.call(ret) - } - } catch (e: JSONException) { - Log.e(logTag, "The response received did not conform to our expected JSON format.", e) - } - } + override fun run() { + Log.i(logTag, message) + // new format + // {"data": {"utterance": "There are only two hard problems in Computer Science: cache invalidation, naming things and off-by-one-errors."}, "type": "speak", "context": null} + try { + val messageObj = Json.decodeFromString(message) + if (messageObj.type == "speak") { + callback.call(Utterance(messageObj.data.utterance, UtteranceFrom.MYCROFT)) + } + } catch (e: SerializationException) { + Log.e(logTag, "The response received did not conform to our expected JSON format.", e) + } + } } diff --git a/mobile/src/main/java/mycroft/ai/entity/JSONMessage.kt b/mobile/src/main/java/mycroft/ai/entity/JSONMessage.kt new file mode 100644 index 00000000..cf8e7f5e --- /dev/null +++ b/mobile/src/main/java/mycroft/ai/entity/JSONMessage.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017. Mycroft AI, Inc. + * + * This file is part of Mycroft-Android a client for Mycroft Core. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package mycroft.ai.entity + +import kotlinx.serialization.Serializable + +@Serializable +data class JSONMessage( + val data: JSONMessageData, + val type: String, + val context: String? +) + diff --git a/mobile/src/main/java/mycroft/ai/entity/JSONMessageData.kt b/mobile/src/main/java/mycroft/ai/entity/JSONMessageData.kt new file mode 100644 index 00000000..3a3aebf5 --- /dev/null +++ b/mobile/src/main/java/mycroft/ai/entity/JSONMessageData.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017. Mycroft AI, Inc. + * + * This file is part of Mycroft-Android a client for Mycroft Core. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package mycroft.ai.entity + +import kotlinx.serialization.Serializable + +@Serializable +data class JSONMessageData( + val utterance: String +) \ No newline at end of file diff --git a/mobile/src/main/java/mycroft/ai/entity/JSONSendMessage.kt b/mobile/src/main/java/mycroft/ai/entity/JSONSendMessage.kt new file mode 100644 index 00000000..d1cb3cab --- /dev/null +++ b/mobile/src/main/java/mycroft/ai/entity/JSONSendMessage.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017. Mycroft AI, Inc. + * + * This file is part of Mycroft-Android a client for Mycroft Core. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package mycroft.ai.entity + +import kotlinx.serialization.Serializable + +@Serializable +data class JSONSendMessage( + val data: JSONSendMessageData, + val type: String, + val context: String? +) \ No newline at end of file diff --git a/mobile/src/main/java/mycroft/ai/entity/JSONSendMessageData.kt b/mobile/src/main/java/mycroft/ai/entity/JSONSendMessageData.kt new file mode 100644 index 00000000..01f4213d --- /dev/null +++ b/mobile/src/main/java/mycroft/ai/entity/JSONSendMessageData.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017. Mycroft AI, Inc. + * + * This file is part of Mycroft-Android a client for Mycroft Core. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package mycroft.ai.entity + +import kotlinx.serialization.Serializable + +@Serializable +data class JSONSendMessageData( + val utterances: List +)