MQTT 是一種輕量級的、靈活的物聯網訊息交換和資料傳遞協議,致力於為 IoT 開發人員實現靈活性與硬體/網路資源的平衡。
Kotlin 是一門由 JetBrains 公司開發的程式語言,Kotlin 是基於 JVM 的,所以開發者可以很方便地用它來進行 Android 開發,並且支援 Kotlin 和 Java 的混合編寫。而早在 2017 年,Google 就宣佈 Kotlin 成為官方開發語言。
本文主要介紹使用 Kotlin 語言在 Android 平臺上使用 MQTT。
新建 Kotlin 專案
開啟 Android Studio 新建一個專案,選擇語言為 Kotlin,Android Studio 會自動建立 Kotlin 相關配置。若要配置現有專案,則可以參考 將 Kotlin 新增到現有應用。
新增依賴
開啟專案的 build.gradle
,新增 Eclipse Paho Java Client 和 Eclipse Paho Android Service 依賴到 dependencies
部分。
dependencies {
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.4'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}
配置 AndroidManifest.xml
Android Service 是 Eclipse 開發的基於 Android 平臺的一個後臺服務,我們需要將它註冊到AndroidManifest.xml 檔案,同時,我們需要註冊許可權。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
...
<service android:name="org.eclipse.paho.android.service.MqttService" />
</application>
建立 MQTT 客戶端
private lateinit var mqttClient: MqttAndroidClient
// TAG
companion object {
const val TAG = "AndroidMqttClient"
}
連線 MQTT 伺服器
本文將使用 EMQ X MQTT Cloud 運營和維護的免費公共 MQTT 伺服器, EMQ X Cloud 是由 EMQ 推出的安全的 MQTT 物聯網雲服務平臺,它提供一站式運維代管、獨有隔離環境的 MQTT 5.0 接入服務。
- Broker: broker.emqx.io
- TCP Port: 1883
- Websocket Port: 8083
fun connect(context: Context) {
val serverURI = "tcp://broker.emqx.io:1883"
mqttClient = MqttAndroidClient(context, serverURI, "kotlin_client")
mqttClient.setCallback(object : MqttCallback {
override fun messageArrived(topic: String?, message: MqttMessage?) {
Log.d(TAG, "Receive message: ${message.toString()} from topic: $topic")
}
override fun connectionLost(cause: Throwable?) {
Log.d(TAG, "Connection lost ${cause.toString()}")
}
override fun deliveryComplete(token: IMqttDeliveryToken?) {
}
})
val options = MqttConnectOptions()
try {
mqttClient.connect(options, null, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken?) {
Log.d(TAG, "Connection success")
}
override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
Log.d(TAG, "Connection failure")
}
})
} catch (e: MqttException) {
e.printStackTrace()
}
}
其中,MqttCallback
介面包含 3 個方法:
- messageArrived:收到 broker 新訊息
- connectionLost:與 broker 連線丟失
- deliveryComplete:訊息到 broker 傳遞完成
MqttConnectOptions
用於配置連線設定,包含使用者名稱密碼,超時配置等,具體可以檢視其方法。
建立 MQTT 訂閱
訂閱 topic
fun subscribe(topic: String, qos: Int = 1) {
try {
mqttClient.subscribe(topic, qos, null, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken?) {
Log.d(TAG, "Subscribed to $topic")
}
override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
Log.d(TAG, "Failed to subscribe $topic")
}
})
} catch (e: MqttException) {
e.printStackTrace()
}
}
取消訂閱
取消訂閱 topic
fun unsubscribe(topic: String) {
try {
mqttClient.unsubscribe(topic, null, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken?) {
Log.d(TAG, "Unsubscribed to $topic")
}
override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
Log.d(TAG, "Failed to unsubscribe $topic")
}
})
} catch (e: MqttException) {
e.printStackTrace()
}
}
釋出訊息
fun publish(topic: String, msg: String, qos: Int = 1, retained: Boolean = false) {
try {
val message = MqttMessage()
message.payload = msg.toByteArray()
message.qos = qos
message.isRetained = retained
mqttClient.publish(topic, message, null, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken?) {
Log.d(TAG, "$msg published to $topic")
}
override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
Log.d(TAG, "Failed to publish $msg to $topic")
}
})
} catch (e: MqttException) {
e.printStackTrace()
}
}
斷開 MQTT 連線
fun disconnect() {
try {
mqttClient.disconnect(null, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken?) {
Log.d(TAG, "Disconnected")
}
override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
Log.d(TAG, "Failed to disconnect")
}
})
} catch (e: MqttException) {
e.printStackTrace()
}
}
測試
首先將 Android 客戶端連線到 MQTT 伺服器,然後訂閱 topic: a/b
,可以看到連線成功和成功訂閱的日誌
然後我們使用 MQTT 5.0 客戶端工具 - MQTT X 進行測試,釋出訊息到 topic: a/b
,客戶端可以看到收到訊息的日誌
我們在客戶端釋出訊息到 topic: a/b
,因為我們訂閱了該 topic,同時也會收到訊息,最後我們斷開客戶端與 MQTT 伺服器的連線,日誌如下:
至此,我們已經完成了Android 上 MQTT 客戶端的構建,實現了客戶端與 MQTT 伺服器的連線、主題訂閱、收發訊息等功能。
MQTT 可以以極少的程式碼和有限的頻寬,為連線遠端裝置提供實時可靠的訊息服務。作為一種低開銷、低頻寬佔用的即時通訊協議,使其在物聯網、小型裝置、移動應用等方面有較廣泛的應用。
而 Kotlin 也是 Google 官方主推的一門語言,結合 MQTT 協議及 MQTT 雲服務,我們可以開發更多有趣的應用。
版權宣告: 本文為 EMQ 原創,轉載請註明出處。