Android 本地推送 Mqtt

引用

compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'

添加服务

  自定义服务 保持mq的服务和自己的服务在同一进程中 不然会出bug
    <service
            android:name=".push.PushService"
            android:exported="false"
            android:process=":push" />
        <service
            android:name="org.eclipse.paho.android.service.MqttService"
            android:process=":push" />

初始化

        this.context = context;
        exit = false
        var uri = "tcp://$host:$port"
//        var uri = "ssl://$host:$port"
        mClient = MqttAndroidClient(context, uri, clientId)

        mClient?.setCallback(this)

        //mqtt连接参数设置
        options = MqttConnectOptions();
        //设置自动重连
        options?.isAutomaticReconnect = false;
        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录
        // 这里设置为true表示每次连接到服务器都以新的身份连接
        options?.isCleanSession = false;
        // 设置超时时间 单位为秒
        options?.connectionTimeout = 5;
        // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
        options?.keepAliveInterval = 20;

        //设定(持久订阅,不重复获取推送消息)
        options?.setWill(clientId, ByteArray(100), 2, false);

        /*连接成功之后设置连接断开的缓冲配置*/
        disconnectedBufferOptions = DisconnectedBufferOptions();
        //开启
        disconnectedBufferOptions?.isBufferEnabled = true;
        //离线后最多缓存100调
        disconnectedBufferOptions?.bufferSize = 100;
        //不一直持续留存
        disconnectedBufferOptions?.isPersistBuffer = false;
        //删除旧消息
        disconnectedBufferOptions?.isDeleteOldestMessages = false;

链接

 mClient?.connect(options, null, object : IMqttActionListener {
            override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                Log.e(TAG, "链接失败")
            }

            override fun onSuccess(asyncActionToken: IMqttToken?) {
                Log.e(TAG, "链接成功")
                //订阅
                subscribeToTopic()

            }
        })

消息订阅
消息订阅一定要放到链接成功之后

 mClient?.setBufferOpts(disconnectedBufferOptions)

        //主题、QOS、context,订阅监听,消息监听.   这里用clientID 
        var token = mClient?.subscribe(mClient?.clientId, 2, null, object : IMqttActionListener {
            override fun onSuccess(asyncActionToken: IMqttToken?) {
                Log.e(TAG, "订阅成功")
            }

            override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                Log.e(TAG, "订阅失败")
            }
        }) { topic, message ->
            Log.e(TAG, "$topic  消息到达 $message")
            showMessage(message = message.toString())
        }
        Log.e(TAG, "token ${token?.isComplete}")

消息到了显示的通知栏,这里用之前项目中极光推送,显示的话百度.

源码

自定义的服务

class PushService : Service() {
    private val TAG = PushService::class.java.simpleName
    var pushClient: PushClient? = null

    companion object {
       fun start(context: Context) {
            var bundle = Bundle()
            bundle.putSerializable(Constant.PUSH_ACTION, Action.START)
            var intent = Intent(context, PushService::class.java);
            intent.putExtras(bundle)
            Log.e("PushService", "开始服务")
            context.startService(intent)
        }

        fun connect(context: Context, userId: String) {
            var bundle = Bundle()
            bundle.putSerializable(Constant.PUSH_ACTION, Action.CONNECT)
            bundle.putString(Constant.KEY_USER_ID, userId)
            var intent = Intent(context, PushService::class.java);
            intent.putExtras(bundle)
            Log.e("PushService", "链接服务")
            context.startService(intent)
        }

        fun stop(context: Context) {
            var bundle = Bundle()
            bundle.putSerializable(Constant.PUSH_ACTION, Action.STOP)
            var intent = Intent(context, PushService::class.java);
            intent.putExtras(bundle)
            context.startService(intent)
        }
    }


    override fun onBind(intent: Intent?): IBinder? {

        return null
    }

    override fun onCreate() {
        Log.e(TAG, "onCreate")
        super.onCreate()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.e(TAG, "onStartCommand" + System.currentTimeMillis())
        handleAction(intent)
        return super.onStartCommand(intent, flags, startId)
    }

    private fun handleAction(intent: Intent?) {
        var bundle = intent?.extras
        var action = bundle?.getSerializable(Constant.PUSH_ACTION)
        when (action) {
            Action.START -> {
                Log.e(TAG, "action start")
            }
            Action.CONNECT -> {
                Log.e(TAG, "action connect")
                connect(bundle!!.getString(Constant.KEY_USER_ID))
            }
            Action.STOP -> {
                Log.e(TAG, "action stop")
                disConnect()
            }
        }
    }

    fun connect(userId: String) {
        if (pushClient == null) {
            Log.e(TAG, "pushClient create")
            pushClient = PushClient.create(Constant.PUSH_HOST, 1883, this, userId)
        } else {
            Log.e(TAG, "pushClient exists")
        }
        pushClient?.connect()
    }

    fun disConnect() {
        pushClient?.disConnect()
        pushClient = null
    }


    override fun onDestroy() {
        Log.e(TAG, "服务销毁")
        super.onDestroy()
    }

}

枚举

enum class Action {
    START,
    CONNECT,
    STOP
}

pushClient 加了重连 网络监听,

class PushClient : MqttCallback {

    private val TAG = "PushClient"


    //mqtt连接client
    var mClient: MqttAndroidClient? = null
    //mqtt连接参数设置
    var options: MqttConnectOptions? = null;
    /*连接成功之后设置连接断开的缓冲配置*/
    var disconnectedBufferOptions: DisconnectedBufferOptions? = null
    var context: Context? = null
    var countDownTimer: CountDownTimer? = null//倒计时重连
    var exit = false//是否退出
    //重连时间间隔  ,分别是 1、2、4、8、16、32、64、128、256、512 秒后
    var array: Array<Long> = arrayOf(1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000, 256000, 512000)
    var iterator: Iterator<Long>? = null

    var connecting = false

    constructor(host: String, port: Int, context: Context, clientId: String) {

        this.context = context;
        exit = false
        var uri = "tcp://$host:$port"
//        var uri = "ssl://$host:$port"
        mClient = MqttAndroidClient(context, uri, clientId)

        mClient?.setCallback(this)

        //mqtt连接参数设置
        options = MqttConnectOptions();
        //设置自动重连
        options?.isAutomaticReconnect = false;
        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录
        // 这里设置为true表示每次连接到服务器都以新的身份连接
        options?.isCleanSession = false;
        // 设置超时时间 单位为秒
        options?.connectionTimeout = 5;
        // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
        options?.keepAliveInterval = 20;

        //设定(持久订阅,不重复获取推送消息)
        options?.setWill(clientId, ByteArray(100), 2, false);

        /*连接成功之后设置连接断开的缓冲配置*/
        disconnectedBufferOptions = DisconnectedBufferOptions();
        //开启
        disconnectedBufferOptions?.isBufferEnabled = true;
        //离线后最多缓存100调
        disconnectedBufferOptions?.bufferSize = 100;
        //不一直持续留存
        disconnectedBufferOptions?.isPersistBuffer = false;
        //删除旧消息
        disconnectedBufferOptions?.isDeleteOldestMessages = false;
        initReceiver()
        iterator = array.iterator()
    }

    companion object {
        fun create(host: String, port: Int, context: Context, clientId: String): PushClient {
            return PushClient(host = host, port = port, context = context, clientId = clientId)
        }
    }

    /**
     * 链接
     */
    fun connect() {

        if (connecting) {
            Log.e(TAG, " 正在链接中请等待")
            return
        }
        connecting = true
        Log.e(TAG, "链接${mClient?.serverURI}")
        mClient?.connect(options, null, object : IMqttActionListener {
            override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                Log.e(TAG, "链接失败")
                connecting = false
                resetConnect()
            }

            override fun onSuccess(asyncActionToken: IMqttToken?) {
                connecting = false
                Log.e(TAG, "链接成功")
                if (countDownTimer != null) {
                    countDownTimer?.cancel()
                    countDownTimer = null
                }
                //订阅
                subscribeToTopic()
                //重置重连时间
                resetConnectTime()
            }
        })
    }

    /**
     * 注册网络监听
     */
    fun initReceiver() {
        var timeFilter = IntentFilter();
//        timeFilter.addAction("android.net.ethernet.ETHERNET_STATE_CHANGED");
//        timeFilter.addAction("android.net.ethernet.STATE_CHANGE");
//        timeFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//        timeFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
//        timeFilter.addAction("android.net.wifi.STATE_CHANGE");
//        timeFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        timeFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        context?.registerReceiver(object : BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                Log.e(TAG, "网络发生变化")
                resetConnectTime()
                if (!mClient!!.isConnected) {
                    resetConnect()
                }
            }

        }, timeFilter);
    }

    fun resetConnectTime() {
        if (countDownTimer != null) {
            countDownTimer?.cancel()
            countDownTimer = null
        }
        iterator = array.iterator()
    }

    /**
     * 重新链接
     */
    fun resetConnect() {
        if (countDownTimer != null) {
            countDownTimer?.cancel()
            countDownTimer = null
        }
        if (connecting) {
            Log.e(TAG, " 正在链接中请等待   稍后重连")
            return
        }
        if (iterator != null && iterator?.hasNext()!!) {
            countDownTimer = object : CountDownTimer(iterator?.next()!!, 1000) {
                override fun onTick(millisUntilFinished: Long) {
                    Log.e(TAG, "等待重新链接  $millisUntilFinished")
                }

                override fun onFinish() {
                    Log.e(TAG, "重新链接")
                    connect()
                }
            }.start()
        } else {
            Log.e(TAG, " 重连次数到上限 暂不重连 ")
        }
    }

    override fun messageArrived(topic: String?, message: MqttMessage?) {
        Log.e(TAG, "messageArrived")
    }

    /**
     * @desc 连接断开回调
     * 可在这里做一些重连等操作
     */
    override fun connectionLost(cause: Throwable?) {
        Log.e(TAG, "connectionLost")
        if (!exit) {
            resetConnect()
        }
    }

    override fun deliveryComplete(token: IMqttDeliveryToken?) {
        Log.e(TAG, "deliveryComplete")
    }


    /**
     * 断开链接
     */
    fun disConnect() {
        exit = true
        if (countDownTimer != null) {
            countDownTimer?.cancel()
            countDownTimer = null
        }
        Log.e(TAG, "断开链接")
        mClient?.disconnect(null, object : IMqttActionListener {
            override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                Log.e(TAG, "断开链接失败")

            }

            override fun onSuccess(asyncActionToken: IMqttToken?) {
                Log.e(TAG, "断开链接成功")
            }

        })
    }


    /**
     * 订阅主题
     */
    var set = false

    fun subscribeToTopic() {
        Log.e(TAG, "消息订阅${mClient?.clientId}")

        mClient?.setBufferOpts(disconnectedBufferOptions)

        //主题、QOS、context,订阅监听,消息监听
        var token = mClient?.subscribe(mClient?.clientId, 2, null, object : IMqttActionListener {
            override fun onSuccess(asyncActionToken: IMqttToken?) {
                Log.e(TAG, "订阅成功")
            }

            override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                Log.e(TAG, "订阅失败")
            }
        }) { topic, message ->
            Log.e(TAG, "$topic  消息到达 $message")
            showMessage(message = message.toString())
        }
        Log.e(TAG, "token ${token?.isComplete}")
    }

    /**
     * 是否链接
     */
    fun isConnected(): Boolean {
        return if (mClient == null) {
            false
        } else {
            mClient!!.isConnected
        }
    }


    private fun showMessage(message: String) {
        val jsonObject = JSONObject(message)
        val ln = JPushLocalNotification()
        ln.extras = message
        ln.builderId = 0
        ln.content = jsonObject.getString("content")
        ln.title = jsonObject.getString("title")
        ln.notificationId = System.currentTimeMillis()
        ln.broadcastTime = System.currentTimeMillis() + 1000 * 1
        JPushInterface.addLocalNotification(context, ln)
    }

}

使用方法

PushService.start
PushService.connect
PushService.stop

猜你喜欢

转载自blog.csdn.net/weixin_33695082/article/details/86836954