Android使用Mqtt案例

MQTT的github地址是: https://github.com/mqtt/mqtt.github.io/wiki/software?id=software

在它推薦的 Servers/Brokers中就是我上一篇中提到的 Moquette,當然還有Apache ActiveMQ也是不錯的。

在客戶端推薦中,Eclipse Paho Java是Java語言的首選,phpMQTT則是PHP語言的首選。

那麼在Android開發中,我們同樣可以使用 Eclipse Paho Java,地址是: https://www.eclipse.org/paho/clients/java/

其實這個 Eclipse Paho Java對我們來講,就是一個JAR包而已,

下載地址爲:https://repo.eclipse.org/content/repositories/paho-releases/

在這裏我下載了 org.eclipse.paho.client.mqttv3-1.1.1.jar

在我們使用mqtt的時候,我們優先要保證有一個代理服務器(Moquette)在運行,且能夠訪問1883端口!

我們構建一個Android工程,實現最簡單的訂閱和發佈功能。

我們構建了兩個按鈕,一個用來訂閱,一個用來發布。

MainActivity.java 部分代碼如下:

    // 代理服務器地址
    public static final String HOST = "tcp://192.168.16.61:1883";
    // 自定義主題
    public static final String TOPIC = "richie";
    // 自定義消息
    public static final String CONTENT = "hello";
    // 消息質量
    public static final int qos = 1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        subscribeButton = findViewById(R.id.subscribe_button);
        subscribeButton.setOnClickListener(this);

        publishButton = findViewById(R.id.publish_button);
        publishButton.setOnClickListener(this);

        data = new ArrayList<>();
        messageListview = findViewById(R.id.message_listview);
        adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,data);
        messageListview.setAdapter(adapter);
    }


    @Override
    public void onClick(View v) {

        // 訂閱
        if(v.getId() == R.id.subscribe_button){

            try {
                addMessage("點擊訂閱按鈕......");
                SubscribeClient subscribeClient = new SubscribeClient(this);
                subscribeClient.subscribe();
            } catch (MqttException e){ e.printStackTrace(); }
            catch(Exception e) { e.printStackTrace(); }
        }

        // 發佈
        if(v.getId() == R.id.publish_button){

            try {
                addMessage("點擊發布按鈕......");
                PublishClient publishClient = new PublishClient(this);
                publishClient.publish();
            } catch (MqttException e){ e.printStackTrace(); }
            catch(Exception e) { e.printStackTrace(); }
        }
    }

上面的代碼比較簡單,就是點擊按鈕觸發兩個客戶端來完成訂閱和發佈功能。

我先看訂閱客戶端 SubscribeClient.java 部分代碼如下:

    // 連接客戶端
    private MqttClient client;
    private String clientid = "subscribe_client";


    // MainActivity引用
    private MainActivity mainActivity = null;


    // 構造方法,實例化客戶端並連接
    public SubscribeClient(MainActivity mainActivity) throws MqttException {

        // MainActivity引用
        this.mainActivity = mainActivity;

        // 構建包含連接參數的連接選擇對象
        MqttConnectOptions options = new MqttConnectOptions();
        // 設置Mqtt版本
        options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
        // 設置清空Session,false表示服務器會保留客戶端的連接記錄,true表示每次以新的身份連接到服務器
        options.setCleanSession(false);
        // 設置超時時間,單位爲秒
        options.setConnectionTimeout(30);
        // 設置會話心跳時間,單位爲秒,客戶端每隔10秒向服務端發送心跳包判斷客戶端是否在線
        options.setKeepAliveInterval(10);
        // 客戶端是否自動嘗試重新連接到服務器
        options.setAutomaticReconnect(true);

        // 創建MQTT客戶端併發起連接代理服務器
        client = new MqttClient(MainActivity.HOST, clientid, new MemoryPersistence());
        // 設置回調
        client.setCallback(new PushCallback(this.mainActivity, this.clientid));
        // 發起連接
        client.connect(options);
    }


    // 訂閱指定主題
    public void subscribe() throws MqttException {

        client.subscribe(MainActivity.TOPIC, MainActivity.qos);
    }

訂閱完成之後,接受消息實際是在回調類中實現的,也就是PushCallback,我們先看 PublishClient.java裏面:

    // 連接客戶端
    private MqttClient client;
    private String clientid = "publish_client";

    // MainActivity引用
    private MainActivity mainActivity = null;


    // 構造函數,實例化客戶端並連接代理服務器
    public PublishClient(MainActivity mainActivity) throws MqttException {

        // MainActivity引用
        this.mainActivity = mainActivity;

        // 構建包含連接參數的連接選擇對象
        MqttConnectOptions options = new MqttConnectOptions();
        // 設置Mqtt版本
        options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
        // 設置清空Session,false表示服務器會保留客戶端的連接記錄,true表示每次以新的身份連接到服務器
        options.setCleanSession(false);
        // 設置超時時間,單位爲秒
        options.setConnectionTimeout(30);
        // 設置會話心跳時間,單位爲秒,客戶端每隔10秒向服務端發送心跳包判斷客戶端是否在線
        options.setKeepAliveInterval(10);
        // 客戶端是否自動嘗試重新連接到服務器
        options.setAutomaticReconnect(true);

        // 創建MQTT客戶端併發起連接代理服務器
        client = new MqttClient(MainActivity.HOST, clientid, new MemoryPersistence());
        // 設置回調
        client.setCallback(new PushCallback(this.mainActivity, this.clientid));
        // 發起連接
        client.connect(options);
    }


    // 發佈消息
    public void publish() throws MqttException {

        // 定義消息:hello
        MqttMessage message = new MqttMessage();
        message.setQos(MainActivity.qos);
        message.setPayload(MainActivity.CONTENT.getBytes());

        // 發佈消息
        client.publish(MainActivity.TOPIC, message);
    }

需要注意的是,發佈的主題要和訂閱的主題一致,這樣剛纔的訂閱客戶端才能收到。

雖然我們是在同一個Activity裏面即完成訂閱又發佈的功能,但是我們定義了兩個不同的客戶端,clientid是不同的。

大家可能注意到,訂閱和發佈的回調類是同一個 PushCallback,它繼承自 org.eclipse.paho.client.mqttv3.MqttCallback

    // 客戶端ID
    private String clientid = "";

    // MainActivity引用
    private MainActivity mainActivity = null;


    // 構造方法
    public PushCallback(MainActivity mainActivity, String clientid) {

        this.mainActivity = mainActivity;
        this.clientid = clientid;
    }


    // 在斷開連接時調用
    @Override
    public void connectionLost(Throwable throwable) {

        System.out.println(this.clientid + "連接已斷開!");
        mainActivity.addMessage(this.clientid + "連接已斷開!");
    }


    // 接收訂閱主題消息的回調
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {

        System.out.println("接收消息主題 : " + topic);
        System.out.println("接收消息Qos : " + message.getQos());
        System.out.println("接收消息內容 : " + new String(message.getPayload()));
        mainActivity.addMessage("接收消息內容 : " + new String(message.getPayload()));
    }


    // 接收發布主題消息的回調
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {

        System.out.println("發佈消息回調:" + token.isComplete());
        mainActivity.addMessage("發佈消息回調:" + token.isComplete());
    }

上面繼承的方法裏面說明很清楚,一個用來判斷客戶端是否連接代理服務器(Moquette),一個用來接收消息,

一個用來做發佈消息的回調,整個工程效果如下:

同時,我們在代理服務器(Moquette)運行狀態中,也能看到來自兩個客戶端的連接,

在服務器日誌中,我們清晰的看到客戶端的連接,以及訂閱和發佈操作。

這個工程連同Jar包我已經上傳CSDN,下載地址是:  https://download.csdn.net/download/konkon2012/11685143

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章