基于MQTT的推送,连接服务器问题

来源:互联网 发布:淘宝魅力惠官方旗舰店 编辑:程序博客网 时间:2024/06/06 02:33

最近,项目中要实现基于MQTT协议IM功能。此时,觉得头疼,赶紧问问MQTT的官网,看看这玩意到底是怎么一回事。看过之后,哇哦,还挺神奇的,了解之后,我们自己就可以开发即时通讯了,还用什么第三方的类库啊。好了,闲话不多说,我们进入正题吧。

第一:MQTT的简介

MQTT轻量发布订阅消息协议

概览

MQTT是一个轻量的发布订阅模式消息传输协议,专门针对低带宽和不稳定网络环境的物联网应用设计。

MQTT官网: http://mqtt.org

MQTT V3.1.1协议规范: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html

特点

1.开放消息协议,简单易实现
2.发布订阅模式,一对多消息发布
3.基于TCP/IP网络连接
4.1字节固定报头,2字节心跳报文,报文结构紧凑
5.消息QoS支持,可靠传输保证

应用

MQTT协议广泛应用于物联网、移动互联网、智能硬件、车联网、电力能源等领域。

1.物联网M2M通信,物联网大数据采集
2.Android消息推送,WEB消息推送
3.移动即时消息,例如Facebook Messenger
4.智能硬件、智能家具、智能电器
5.车联网通信,电动车站桩采集
6.智慧城市、远程医疗、远程教育
7.电力、石油与能源等行业市场

下面附上MQTT协议的中文连接:http://docs.emqtt.cn/zh_CN/latest/mqtt.html

第二:需要配置的文件

1.在build.gradle文件中添加所需的包。

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

以为这两个一添加就完了嘛???对,没有,如果只是这样的话,是永远收不到推送的,最关键的就是第二步。
2.在AndroidManifest.xml文件中添加如下代码:

 <service android:name="org.eclipse.paho.android.service.MqttService" />

有人可能会有疑问,还要添加这行嘛,对,没错,必须添加。

现在所有的准备工作做完了,让我们连接服务器吧。

第三:连接服务器

我在代码中,书写了相关的注释,大家看代码,这里就不多解释了,如果有不懂的,可以看看上面的中文连接的MQTT协议。

public class MqttTest {    private static final String TAG = "MqttTest";    private static final String MQTT_BROKER = "后台的地址"; // Broker URL or IP Address    private static final String MQTT_PORT = "端口号"; // Broker Port    private static final String MQTT_URL_FORMAT = "tcp://%s:%s"; // URL Format normally don't change    private String myTopic = "test/topic";    private ScheduledExecutorService scheduler;    private MqttAsyncClient mqttClient;    private String userName = "admin"; // 连接的用户名    private String passWord = "123456"; //连接的密码    private String mDeviceId = "";       // Device ID, Secure.ANDROID_ID    private ConnectivityManager mConnectivityManager; // To check for connectivity changes    private MqttConnectOptions options;    private Context context;    public MqttTest(Context context) {        this.context = context;    }    /**     * 初始化相关数据     */    public void init() {        try {            //host为主机名,test为clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存            String url = String.format(Locale.US, MQTT_URL_FORMAT, MQTT_BROKER, MQTT_PORT);            String clientId = String.valueOf(System.currentTimeMillis());            mqttClient = new MqttAsyncClient(url, clientId, new MemoryPersistence());            //MQTT的连接设置            options = new MqttConnectOptions();            //设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接            options.setCleanSession(true);            //设置连接的用户名            options.setUserName(userName);            //设置连接的密码            options.setPassword(passWord.toCharArray());            // 设置超时时间 单位为秒            options.setConnectionTimeout(10);            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制            options.setKeepAliveInterval(20);            //设置回调            options.setAutomaticReconnect(true);//设置自动重连//            mqttAsyncClient.connect(connOpts).waitForCompletion();            mqttClient.setCallback(new MqttCallback() {                @Override                public void connectionLost(Throwable cause) {                    //连接丢失后,一般在这里面进行重连                    if (isNetworkAvailable()) {                        reconnectIfNecessary();                    }                }                @Override                public void messageArrived(String topic, MqttMessage message) throws Exception {                    //subscribe后得到的消息会执行到这里面                    Log.e(TAG, "message=:" + message.toString());                }                @Override                public void deliveryComplete(IMqttDeliveryToken token) {                    //publish后会执行到这里                    long messageId = token.getMessageId();                    Log.e(TAG, "messageId=:" + messageId);                }            });        } catch (Exception e) {            e.printStackTrace();        }        mConnectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);        context.registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));    }    /**     * Query's the NetworkInfo via ConnectivityManager     * to return the current connected state     * 通过ConnectivityManager查询网络连接状态     *     * @return boolean true if we are connected false otherwise     * 如果网络状态正常则返回true反之flase     */    private boolean isNetworkAvailable() {        NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();        return (info == null) ? false : info.isConnected();    }    /**     * Checkes the current connectivity     * and reconnects if it is required.     * 重新连接如果他是必须的     */    public synchronized void reconnectIfNecessary() {        if (mqttClient == null || !mqttClient.isConnected()) {            connect();        }    }    private void connect() {        new Thread(new Runnable() {            @Override            public void run() {                try {                    mqttClient.connect(options);                    // 连接成功之后,处理相关逻辑                } catch (Exception e) {                    e.printStackTrace();                    // 连接出错,可以设置重新连接                }            }        }).start();    }    /**     *  调用init() 方法之后,调用此方法。     */    public void startReconnect() {        scheduler = Executors.newSingleThreadScheduledExecutor();        scheduler.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                if (!mqttClient.isConnected() && isNetworkAvailable()) {                    connect();                }            }        }, 0 * 1000, 10 * 1000, TimeUnit.MILLISECONDS);    }    /**     * Receiver that listens for connectivity chanes     * via ConnectivityManager     * 网络状态发生变化接收器     */    private final BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            Log.i("BroadcastReceiver", "Connectivity Changed...");            if (!isNetworkAvailable()) {                Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT).show();                scheduler.shutdownNow();            } else {                startReconnect();            }        }    };}

嗯,相关连接后台的数据,基本上就这么多,看后天给你返回的数据是怎么样,自己拿上用即可。

最后,加上github的例子,
https://github.com/honeylife/paho.mqtt.javascript,可以下载跑起来,看看相关的例子,逻辑特别严谨。

我会在下面的文章,写即时通讯的相关代码,以及聊天界面的实现,还有图片切换时键盘高度的控制等。