AndroidアプリケーションでMQTT受信
今回はAndroidアプリケーションでMQTTを受信するプログラムに挑戦します。UI開発は最新ツール「Jetpack Compose」を使用しています。
MQTTブローカーはMosquittoを利用しました。こちらを参照してください。【https://mosquitto.org/】
あれこれ調べながら作成しましたが、理解が追いつかず、いろいろおかしい箇所もあるかと思います。
もし流用される場合は、適宜修正してください。ご利用は自己責任でお願いいたします。
MQTTの基本的な概念と仕組み
MQTT(Message Queue Telemetry Transport)は、軽量なメッセージングプロトコルで、特に低帯域幅・低電力環境での通信に適しています。
IoT(Internet of Things)デバイスやネットワークアプリケーションの間でデータを効率的にやり取りするために使用されます。
以下にMQTTの基本的な概念と仕組みを分かりやすく解説します。
1.ブローカー(Broker)
MQTTはクライアント間で直接通信せず、メッセージを中継するサーバーを使います。このサーバーをMQTTブローカー(Broker)と呼びます。
ブローカーはクライアントから送信されたメッセージを受け取り、宛先のクライアント送信します。
2.クライアント(Client)
MQTTを使用するデバイスやアプリケーションがクライアントです。
クライアントはブローカーに接続してメッセージを送受信します。1つのブローカーに複数のクライアントが接続できます。
3.トピック(Topic)
メッセージの配信先を識別するためにトピックが使用されます。
トピックは階層的な構造を持っており、「/」で区切られた階層名のような形で表現されます。
(例)test/myTopic
4.パブリッシュ(Publish)
クライアントがメッセージを送信することをパブリッシュと言います。
クライアントは対象のトピックに対してメッセージをパブリッシュすることで、
そのトピックに興味を持っている他のクライアントにメッセージを送信します。
5.サブスクライブ(Subscribe)
クライアントが対象のトピックに対してメッセージを受信することをサブスクライブと言います。
クライアントは興味のあるトピックに対してサブスクライブし、ブローカーはそのトピックに関連するメッセージを送信します。
6.QoS(Quality of Service)
メッセージの配信品質をQoSレベルとして指定できます。QoSレベルには3つあります。
■QoS 0:メッセージが1回だけ配信されることを保証しますが、メッセージの到着が確認されません。
■QoS 1:メッセージが少なくとも1回は到着することが保証されますが、重複が発生する場合があります。
■QoS 2:メッセージが正確に1回だけ到着することが保証されますが、処理に時間がかかることがあります。
【build.gradle(:app)】
MQTTを使用するための次のライブラリを追加しています。
implementation "org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5"
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.sample.samplez'
compileSdk 33
defaultConfig {
applicationId "com.sample.samplez"
minSdk 30
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion '1.3.2'
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.8.0'
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.5.1'
implementation platform('androidx.compose:compose-bom:2022.10.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation platform('androidx.compose:compose-bom:2022.10.00')
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
// MQTTライブラリ
implementation "org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5"
}
【MainActivity.kt】
今回のメインとなるクラスです。MQTT受信したメッセージを画面に表示します。
package com.sample.samplez
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.*
import androidx.compose.ui.tooling.preview.Preview
import org.eclipse.paho.client.mqttv3.*
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
import java.nio.charset.Charset
class MainActivity : ComponentActivity() {
//エミュレータでlocalhostを指定する場合は「10.0.2.2」を使うべし
private val mqttServerUri = "tcp://10.0.2.2:1883"
private val mqttTopic = "test/Topic1"
private lateinit var mqttClient: MqttClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val messageState = remember { mutableStateOf("") }
MqttSubscriptionApp(messageState)
// MQTTサブスクライブ
startMqttSubscription(messageState)
}
}
private fun startMqttSubscription(messageState: MutableState) {
try {
mqttClient = MqttClient(mqttServerUri, MqttClient.generateClientId(), MemoryPersistence())
val options = MqttConnectOptions()
options.isAutomaticReconnect = true
options.isCleanSession = false
mqttClient.connect(options)
mqttClient.setCallback(object : MqttCallback {
override fun connectionLost(cause: Throwable?) {
// 接続が失われたときの処理
}
override fun messageArrived(topic: String?, message: MqttMessage?) {
// 新しいメッセージが到着したときの処理
val receivedMessage = message?.toString()
if (!receivedMessage.isNullOrEmpty()) {
// UTF-8に変換する
val utf8String = receivedMessage.toByteArray(Charset.forName("UTF-8"))
// UTF-8に変換されたバイト配列を文字列に戻す
val convertedString = String(utf8String, Charset.forName("UTF-8"))
// messageStateの値を更新する
messageState.value = convertedString
}
}
override fun deliveryComplete(token: IMqttDeliveryToken?) {
// メッセージの送信が完了したときの処理
}
})
mqttClient.subscribe(mqttTopic, 0)
} catch (e: MqttException) {
e.printStackTrace()
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MqttSubscriptionApp(messageState: MutableState) {
Column {
TopAppBar(title = { Text(text = "MQTTで受信してみよう") })
Surface {
Column {
Text(text = "受信したメッセージ:")
Text(text = messageState.value)
}
}
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
MaterialTheme {
val messageState = remember { mutableStateOf("") }
MqttSubscriptionApp(messageState)
}
}
動作確認
下記の手順で動作確認を行います。受信が成功していれば画面に受信したメッセージが表示されます。
手順1
まずはAndroid Studioでエミュレータを起動し、作成したアプリケーションを実行します。
手順2
今回はWindows版のMosquittoをc:\Program Filesにインストールしてあります。
コマンドプロンプトで下記コマンドを実行し、MQTTブローカーを起動します。
"c:\Program Files\mosquitto\mosquitto.exe" -v
手順3
手順2とは別のコマンドプロンプトを起動し、下記コマンドを実行して"SEND MESSAGE"というメッセージを送信してみます。
"c:\Program Files\mosquitto\mosquitto_pub.exe" -h localhost -t "test/Topic1" -m "SEND MESSAGE"
手順4
アプリケーションの画面に受信したメッセージが表示されたことを確認します。
今回はKotlinでMQTTのメッセージを受信するサンプルプログラムを紹介しました。 どんな感じか掴むことができましたか?
よく分からないという人は、全部まとめてではなく、少しずつ自分でいろいろ試してみると良いかも知れません。 頑張っていきましょう!