10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AndroidでMQTTのトピックをサブスクライブし、スマホ画面上にメッセージを表示

Posted at

やりたいこと

AndroidアプリでMQTTのトピックをサブスクライブし、スマホ画面上にメッセージを表示したい。

絵にすると

[外部サーバー(MQTT Broker)] -> [Android(subscriber)]

なぜこんなことをやるのか

外部のMQTTブローカーからのメッセージをサブスクライブし内容確認を行う部分をアプリ化することで、非エンジニアの方にもアプリをインストールさえすれば利用可能にする。
Webアプリ上でサブスクライブも考えたが、認証部分を考えるのが面倒だったのと、Webサーバーを作りたくなかった(手離れを良くしたかった)

補足

参考記事

注意

忘備録ですので、基本的なAndroidアプリの開発方法は書きません。

実装

Android Studio 3.3.2 (OSX版)で実装。

最初に、Empty Activityを作成する。

この Eclipse Paho Android Service ライブラリが数年前からデファクトのようなので、利用する。
https://github.com/eclipse/paho.mqtt.android

gradle

app のGradleに以下を追加

repositories {
    maven {
        url "https://repo.eclipse.org/content/repositories/paho-snapshots/"
    }
}

dependencies {
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0'
    implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'

manifest

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
     ...
        <service android:name="org.eclipse.paho.android.service.MqttService">
        </service>
    </application>

MainActivity.kt

package me.oxoxo.mqttsubscriber

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*
import org.eclipse.paho.android.service.MqttAndroidClient
import org.eclipse.paho.client.mqttv3.*

class MainActivity : AppCompatActivity() {

    private lateinit var mqttAndroidClient: MqttAndroidClient

    private val clientId = System.currentTimeMillis()
    private val serverUri = "tcp://<your-endpoint>:1883"
    private val subscriptionTopic = "<your-topic>"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mqttAndroidClient = MqttAndroidClient(applicationContext, serverUri, clientId.toString())
        mqttAndroidClient.setCallback(object : MqttCallbackExtended {
            override fun connectComplete(reconnect: Boolean, serverURI: String) {

                if (reconnect) {
                    addToHistory("Reconnected to : $serverURI")
                    subscribeToTopic()
                } else {
                    addToHistory("Connected to: $serverURI")
                }
            }

            override fun connectionLost(cause: Throwable) {
                addToHistory("The Connection was lost.")
            }

            @Throws(Exception::class)
            override fun messageArrived(topic: String, message: MqttMessage) {
                addToHistory("Incoming message: " + String(message.payload))

                hello.text = String(message.payload)
            }

            override fun deliveryComplete(token: IMqttDeliveryToken) {}
        })

        val mqttConnectOptions = MqttConnectOptions()
        mqttConnectOptions.isAutomaticReconnect = true
        mqttConnectOptions.isCleanSession = false
        mqttConnectOptions.userName = "<user_name>"
        mqttConnectOptions.password = "<password>".toCharArray()

        try {
            mqttAndroidClient.connect(mqttConnectOptions, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken) {
                    val disconnectedBufferOptions = DisconnectedBufferOptions()
                    disconnectedBufferOptions.isBufferEnabled = true
                    disconnectedBufferOptions.bufferSize = 100
                    disconnectedBufferOptions.isPersistBuffer = false
                    disconnectedBufferOptions.isDeleteOldestMessages = false
                    mqttAndroidClient.setBufferOpts(disconnectedBufferOptions)
                    subscribeToTopic()
                }

                override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
                    addToHistory("Failed to connect to: $serverUri")
                    exception.printStackTrace()
                }
            })

        } catch (ex: MqttException) {
            ex.printStackTrace()
        }
    }

    fun subscribeToTopic() {
        try {
            mqttAndroidClient.subscribe(subscriptionTopic, 0, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken) {
                    addToHistory("Subscribed!")
                }

                override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
                    addToHistory("Failed to subscribe")
                }
            })

        } catch (ex: MqttException) {
            System.err.println("Exception whilst subscribing")
            ex.printStackTrace()
        }
    }

    private fun addToHistory(mainText: String) {
        Log.d("tag","LOG: $mainText")
    }
}

endpoint, topic, user name, password は、環境に合わせて入力する。
activity_main.xmlのTextViewに、 android:id="@+id/hello" を入れて完成。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?