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'

直接上类MQ管理类,用Timetask,30秒进行一次检测连接状态.断开就重连.需要注意的是,每个手机连接的clientId应该是不能变的,要不就会出现重复收到消息之类的各种BUG.

public class MQTTManager {

    private static final String TAG = "MQTTManager";
    private String clientId = "android_";
    private static MQTTManager mqttManager;
    private MqttClient client;
    private MqttConnectOptions options;

    private MsgArrivedListener mMsgArrivedListener;
    private MsgPublishListener mPublishListener;
    private MQConnectListener mConnectListener;

    private TimerTask task;
    private Timer timer;

    private MQTTManager() {
        clientId = clientId + MqttClient.generateClientId();
    }

    public static MQTTManager getInstance() {
        if (mqttManager == null) {
            synchronized (MQTTManager.class) {
                if (mqttManager == null) {
                    mqttManager = new MQTTManager();
                }
            }
        }
        return mqttManager;
    }

    private NetChangeReceiver mNetChangeReceiver;
    private Context unregisterContext;

    public void setNetReceiver(Context context) {
        IntentFilter filter = new IntentFilter();
        //filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        //filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mNetChangeReceiver = new NetChangeReceiver();
        context.registerReceiver(mNetChangeReceiver, filter);
        unregisterContext = context;
    }

    //解除网络变化监听
    public void unregisterNet() {
        if (mNetChangeReceiver != null && unregisterContext != null) {
            unregisterContext.unregisterReceiver(mNetChangeReceiver);
            mNetChangeReceiver = null;
            unregisterContext = null;
        }
    }

    /**
     * 连接服务器
     */
    public void connect() {
        ThreadManage.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "开始连接MQtt");
                try {
                    if (isConnected()) {
                        Log.d(TAG, "已连接过了");
                        if (mConnectListener != null) {
                            mConnectListener.success(true);
                        }
                        return;
                    }
                    // host为主机名,clientId即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
                    client = new MqttClient("tcp://IP地址/端口", clientId, new MemoryPersistence());
                    // MQTT的连接设置
                    options = new MqttConnectOptions();
                    // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
                    options.setCleanSession(false);
                    // 设置连接的用户名
                    options.setUserName("admin");
                    // 设置连接的密码
                    options.setPassword("public".toCharArray());
                    // 设置超时时间 单位为秒
                    options.setConnectionTimeout(30);
                    // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
                    options.setKeepAliveInterval(30);
                    // 设置回调
                    // MqttTopic topic = client.getTopic(TOPIC);
                    //setWill方法,如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
                    //options.setWill(topic, "close".getBytes(), 2, true);
                    client.setCallback(new PushCallback());
                    client.connect(options);
                    if (client.isConnected() && mConnectListener != null) {
                        mConnectListener.success(true);
                        startCheck();
                        UserInfoManager.getInstance().putMQId(clientId);
                    }
                    MagicLog.d("ClientId=" + client.getClientId());
                } catch (MqttException e) {
                    e.printStackTrace();
                    MagicLog.e("MqttException connect: " + e);
                }
            }
        });
    }

    private void startCheck() {
        if (timer == null) {
            timer = new Timer();
        }
        if (task == null) {
            task = new TimerTask() {
                @Override
                public void run() {
                    MagicLog.d("开始检测MQ=========");
                    if (isConnected()) {
                        MagicLog.d("状态正常=========");
                    } else {
                        MagicLog.d("连接断开=========");
                        connect();
                    }
                }
            };
            timer.schedule(task, 100, CommonConstant.BEAT);
            MagicLog.d("========================起动检测MQTT=======================");
        }
        
    }

    /**
     * 订阅消息
     *
     * @param topic 订阅消息的主题
     */
    public void subscribeMsg(String topic, int qos) {
        if (client != null) {
            int[] Qos = {qos};
            String[] topic1 = {topic};
            try {
                client.subscribe(topic1, Qos);
                MagicLog.d("开始订阅topic: " + topic);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    //取消订阅
    public void unSubscribeMsg(String topic, int qos) {
        if (client != null) {
            //int[] Qos = {qos};
            String[] topic1 = {topic};
            try {
                client.unsubscribe(topic1);
                MagicLog.d("取消订阅topic: " + topic);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发布消息
     *
     * @param topic      发布消息主题
     * @param msg        消息体
     * @param isRetained 是否为保留消息
     */
    public void publish(String topic, String msg, boolean isRetained, int qos) {
        try {
            if (client != null) {
                MqttMessage message = new MqttMessage();
                message.setQos(qos);
                message.setRetained(isRetained);
                message.setPayload(msg.getBytes());
                client.publish(topic, message);
                MagicLog.d("发布消息:" + msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (mPublishListener != null) {
                mPublishListener.messagePublishOk(false);
            }
        }
    }

    /**
     * 发布和订阅消息的回调
     */
    public class PushCallback implements MqttCallback {

        public void connectionLost(Throwable cause) {
            MagicLog.e("------连接丢失 connectionLost:" + cause);
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken token) {
            //发布消息的回调,publish后会执行到这里
            //MagicLog.d("发布消息成功的回调" + token.isComplete());
            if (mPublishListener != null) {
                mPublishListener.messagePublishOk(token.isComplete());
            }
        }

        @Override
        public void messageArrived(final String topicName, final MqttMessage message) throws Exception {
            //接收消息的回调方法,subscribe后得到的消息会执行到这里面
            MagicLog.d("接收到消息:" + new String(message.getPayload()));
            if (mMsgArrivedListener != null) {
                mMsgArrivedListener.messageArrived(topicName, new String(message.getPayload()));
            }
        }
    }

    //断开链接
    public void disconnect() {
        if (client != null && client.isConnected()) {
            try {
                client.disconnect();
                release();
                mqttManager = null;
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    //释放资源
    private void release() {
        if (task != null) {
            task.cancel();
            task = null;
        }
        if (timer != null) {
            timer.purge();
            timer.cancel();
            timer = null;
        }
    }

    //判断服务是否连接
    public boolean isConnected() {
        if (client != null) {
            return client.isConnected();
        }
        return false;
    }

    public void setMsgArrivedListener(MsgArrivedListener listener) {
        mMsgArrivedListener = listener;
    }

    public void setConnectListener(MQConnectListener connectListener) {
        mConnectListener = connectListener;
    }

    public void setPublishListener(MsgPublishListener publishListener) {
        mPublishListener = publishListener;
    }

    //消息到达监听
    public interface MsgArrivedListener {
        void messageArrived(String topicName, String content);
    }

    //发布消息监听
    public interface MsgPublishListener {
        void messagePublishOk(boolean isOk);
    }

    //连接MQ监听
    public interface MQConnectListener {
        void success(boolean connect);
    }

    /*public SSLContext sslContextFromStream(InputStream inputStream) throws Exception {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Certificate certificate = certificateFactory.generateCertificate(inputStream);
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", certificate);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
        return sslContext;
    }
    //SSLSocketFactory sslSocketFactory = null;
                   /* try {
                        sslSocket   Factory = sslContextFromStream(mContext.getAssets().open("server.pem")).getSocketFactory();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    options.setSocketFactory(sslSocketFactory);
      */

}

 

监听网络变化类:

public class NetChangeReceiver extends BroadcastReceiver {
    private int count = 0;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            //MagicLog.d("===================网络改变==================");
            //进行网络验证
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
            if (networkInfo != null && networkInfo.isAvailable()) {
                MagicLog.d("===================网络可用");
                if (count != 0) {
                    MagicLog.d("===================网络可用,开始连接MQTTManager==================");
                    MQTTManager manager = MQTTManager.getInstance();
                    manager.connect();
                }
                //EventBus.getDefault().post(new EventNetChange(true));
            } else {
                MagicLog.d("===================网络不可用==================");
                //EventBus.getDefault().post(new EventNetChange(false));
            }
            //MagicLog.d("===================网络变化count==================:" + 0);
            count++;
        }
    }
    
}

最后就是使用了.进入主页调用:

private MQTTManager mMqttManager;

private void initMQ() {
        mMqttManager = MQTTManager.getInstance();
        mMqttManager.connect();
        mMqttManager.setNetReceiver(this);
        mMqttManager.setConnectListener(connect -> {
            subscribeMessage();
        });
        //发布消息回调,处理UI
        mMqttManager.setPublishListener(isOk -> {
            if (isOk) {
                MagicLog.d("发布消息成功");
            } else {
                MagicLog.d("发布消息失败,重连");
                mMqttManager.connect();
            }
        });
    }

    private void subscribeMessage() {
        mMqttManager.setMsgArrivedListener((topicName, content) -> {
            //处理接收到的消息

        });
        //订阅Server端消息
        mMqttManager.subscribeMsg("topic", 2);
    }

 @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMqttManager != null) {
            mMqttManager.unregisterNet();
            mMqttManager.disconnect();
        }
    }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值