Android MQTT

    //MQTT
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
    implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'//MQTT的androidX支持
     
import android.content.Context
import com.jmj.helmet.expansion.myLog
import org.eclipse.paho.android.service.MqttAndroidClient
import org.eclipse.paho.client.mqttv3.*
import java.util.*
import java.util.concurrent.CopyOnWriteArrayList


object MqttManager {
    /**
     * MQTT客户端
     */
    private var mqttAndroidClient: MqttAndroidClient? = null
    /**
     * MQTT配置
     */
    private var mqttConnectOptions: MqttConnectOptions? = null
    /**
     * IP与端口
     */
    private var host: String? = null
    /**
     * 客户端标识 必须唯一
     */
    private var clientId: String? = null
    /**
     * 用户名 密码
     */
    private var un: String? = null
    private var psw: String? = null
    /**
     * 连接超时时间
     */
    private var TIME_OUT_CONNECT = 10
    /**
     * 心跳包间隔
     */
    private var HEARTBEAT_INTERVAL = 10
    /**
     * 重连等待时间
     */
    private var reconnectWaitTime = 5000L
    /**
     * 连接失败/断开连接时 是否启动重连
     */
    private var isReconnect = true
    /**
     * 订阅的主题 与qos等级
     */
    private var subTopics: Array? = null
    private var subQoss: IntArray? = null

    /**
     * 用于区分回调的类型
     */
    private var ACTION_CONNECT = "ACTION_CONNECT" //连接操作
    private var ACTION_SUB_TOPIC = "ACTION_SUB_TOPIC" //订阅操作


    private var callbacs = CopyOnWriteArrayList()

    /**
     * 用户名和密码是可空的
     */
    fun init(
        host: String,
        clientId: String,
        subTopics: Array,
        subQoss: IntArray,
        userName: String? = null,
        password: String? = null,
        isReconnect: Boolean = true,
        reconnectWaitTime: Long = 5000

    ) {
        this.host = host
        this.clientId = clientId
        this.subTopics = subTopics
        this.subQoss = subQoss
        this.un = userName
        this.psw = password
        this.isReconnect = isReconnect
        this.reconnectWaitTime = reconnectWaitTime

    }

    /**
     * 添加监听
     */
    fun addOnMqttCallback(onMqttCallback: OnMqttCallback) {
        callbacs.add(onMqttCallback)
    }

    /**
     * 移除监听
     */
    fun removeOnMqttCallback(onMqttCallback: OnMqttCallback) {
        callbacs.remove(onMqttCallback)
    }

    /**
     * 发送主题消息
     */
    fun publish(topic: String, qos: Int, message: String) {
        myLog("publish: $message")
        mqttAndroidClient?.publish(topic, message.toByteArray(), qos, false)
    }

    /**
     * 连接MQTT服务器
     */
    fun connect(context: Context) {
        if (mqttAndroidClient == null) {
            mqttAndroidClient = MqttAndroidClient(context, host!!, clientId).apply {
                /**
                 * 设置数据回调
                 */
                setCallback(object : MqttCallback {
                    override fun messageArrived(topic: String, message: MqttMessage) {
                        val bytes = message.payload
                        myLog("onNotify:$topic-${String(bytes)}")
                        callbacs.forEach {
                            it.onNotify(topic, bytes)
                        }
                    }

                    override fun deliveryComplete(arg0: IMqttDeliveryToken) {

                    }

                    override fun connectionLost(arg0: Throwable) {
                        myLog("onDisconnect ")
                        callbacs.forEach {
                            it.onDisconnect()
                        }
                        reconnect()
                    }
                })
            }
        }

        if (mqttConnectOptions == null) {
            mqttConnectOptions = MqttConnectOptions()
                .apply {
                    //设置是否清除缓存
                    isCleanSession = true
                    //设置超时时间
                    connectionTimeout = TIME_OUT_CONNECT
                    //设置心跳包发送间隔
                    keepAliveInterval = HEARTBEAT_INTERVAL
                    //设置用户名
                    un?.let {
                        userName = un
                    }
                    //设置密码
                    psw?.let {
                        password = it.toCharArray()
                    }
                }
        }

        if (!mqttAndroidClient!!.isConnected) {
            connect()
        }
    }

    /**
     * 断开连接
     */
    fun disconnect() {
        isReconnect = false
        mqttAndroidClient?.unsubscribe(subTopics)
        mqttAndroidClient?.unregisterResources()
        mqttAndroidClient?.close()
        mqttAndroidClient?.disconnect()
        mqttAndroidClient=null
        mqttConnectOptions=null
    }

    /**
     * 连接MQTT服务器
     */
    private fun connect() {
        myLog("onConnecting")
        callbacs.forEach {
            it.onConnecting()
        }
        mqttAndroidClient!!.connect(mqttConnectOptions, ACTION_CONNECT, iMqttActionListener)
    }

    /**
     * 重连
     */
    private fun reconnect() {
        if (isReconnect) {
            Timer().schedule(object : TimerTask() {
                override fun run() {
                    connect()
                }
            }, reconnectWaitTime)
        }
    }

    /**
     * 订阅主题消息
     */
    private fun subTopic() {
        mqttAndroidClient!!.subscribe(subTopics!!, subQoss!!, ACTION_SUB_TOPIC, iMqttActionListener)
    }

    private var iMqttActionListener = object : IMqttActionListener {
        override fun onSuccess(asyncActionToken: IMqttToken) {
            when (asyncActionToken.userContext.toString()) {
                ACTION_CONNECT -> {
                    myLog("onConnected")
                    callbacs.forEach {
                        it.onConnected()
                    }
                    subTopic()
                }
                ACTION_SUB_TOPIC -> {
                    myLog("onSubTopicSuccess")
                    callbacs.forEach {
                        it.onSubTopicSuccess()
                    }

                }
            }

        }

        override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable?) {
            when (asyncActionToken.userContext.toString()) {
                ACTION_CONNECT -> {
                    myLog("onConnectFail")
                    callbacs.forEach {
                        it.onConnectFail()
                    }

                    reconnect()
                }
                ACTION_SUB_TOPIC -> {
                    myLog("onSubTopicFail")
                    callbacs.forEach {
                        it.onSubTopicFail()
                    }

                }
            }

        }
    }


    interface OnMqttCallback {
        fun onConnecting() {
        }

        fun onConnected() {

        }

        fun onConnectFail() {

        }

        fun onDisconnect() {
        }

        fun onSubTopicSuccess() {

        }

        fun onSubTopicFail() {

        }

        fun onNotify(topic: String, byteArray: ByteArray) {
        }
    }

}

你可能感兴趣的:(Android MQTT)