【Android】AndoidでMQTT
はじめに
Androidでmqttを使ったメッセージの送受信を実装したので、その覚書き
実装にはEclipse Pahoを使用した
開発環境はAndroidStudio Flamingo
実装
まずはbuild.gradleに下記を追記して、依存関係を追加していく
dependencies {
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}
AndroidManifestはネットワーク関連の権限とeclipse.pahoのMqttサービスを追加しておく
<application
<service android:name="org.eclipse.paho.android.service.MqttService" />
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
kotlinで実際にクライアントを作って、MQTTをPublish/Subscribeする部分を書いていく
コード全体は最後に記載する
serverURIの部分は、今回はローカルのmosquittoブローカーと接続する必要があったので、接続先のアドレスは10.0.2.2としている
※AndroidStudioなどの仮想端末から見た場合、ホストのPC端末(仮想端末のホストPC)はアドレス10.0.2.2となる。localhostだとつながらないようなので注意する。
トピックはtestの部分を変えれば良い
private val serverURI = "tcp://10.0.2.2:1883"
private val topic = "test"
コードをそのまま実行するとsubscribeとpublishの両方とも動いてしまうので、注意
必要に応じてコメントアウトなどすること
publish時のメッセージは"hello android"の部分を変えるだけ
subscribeToTopic(topic)
publishMessage(topic, "hello android")
コード全体
class MainActivity : AppCompatActivity() {
val TAG = "Android-Mqtt"
private lateinit var mqttClient: MqttAndroidClient
private val serverURI = "tcp://10.0.2.2:1883"
private val topic = "test"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mqttClient = MqttAndroidClient(this, 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?) {
Log.d(TAG, "Delivery complete")
}
})
connectAndOperateMQTT()
}
private fun connectAndOperateMQTT() {
val options = MqttConnectOptions().apply {
isCleanSession = true
connectionTimeout = 10
keepAliveInterval = 20
}
try {
mqttClient.connect(options, null, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken?) {
Log.d(TAG, "Connection success")
subscribeToTopic(topic)
publishMessage(topic, "hello android")
}
override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
Log.d(TAG, "Connection failure", exception)
}
})
} catch (e: MqttException) {
e.printStackTrace()
}
}
private fun subscribeToTopic(topic: String) {
try {
mqttClient.subscribe(topic, 1, null, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken?) {
Log.d(TAG, "Subscribed to topic $topic")
}
override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
Log.d(TAG, "Failed to subscribe to topic $topic", exception)
}
})
} catch (e: MqttException) {
e.printStackTrace()
}
}
private fun publishMessage(topic: String, message: String) {
try {
val mqttMessage = MqttMessage()
mqttMessage.payload = message.toByteArray()
mqttClient.publish(topic, mqttMessage)
Log.d(TAG, "Message published to topic $topic")
} catch (e: MqttException) {
e.printStackTrace()
}
}
private fun disconnect() {
try {
mqttClient.disconnect(null, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken?) {
Log.d(TAG, "Disconnected successfully")
}
override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
Log.d(TAG, "Failed to disconnect", exception)
}
})
} catch (e: MqttException) {
e.printStackTrace()
}
}
override fun onDestroy() {
super.onDestroy()
if (mqttClient.isConnected) {
disconnect()
}
}
}
所感・注意点
注意点
AndroidのAPIレベルや、使用している環境によっては下記のようなエラーが出る
Failed resolution of: Landroid/support/v4/content/LocalBroadcastManager;
調べると、どうやらEclipse PahoがAndroidの古いサポートライブラリ?を参照しているようで
gradle.propertiesに下記の追記が必要だった
android.enableJetifier=true
android.useAndroidX=true
下記のサイトを含め、いろいろ参考に実装していったが、意外と手間取った。
自分はあまりAndroidアプリ開発に慣れていないので、エラーへの対処法がわからず勉強不足を実感する。
参考サイト
Discussion