Android——MQTT推送

個人博客:haichenyi.com。感謝關(guān)注

整體介紹

??最近公司用到的推送MQTT。不想過多的介紹背景什么的,我就直接講怎么實現(xiàn)這個功能早像。

??他這個原理長連接,這個不用多講肖爵,用法類似于EventBus卢鹦,需要先訂閱,然后通過topic再發(fā)送消息劝堪。topic是什么呢冀自?我先來講講整體流程:

  1. 先連接服務(wù)器揉稚,要先建立長連接

  2. 然后需要訂閱topic,連接之后才能訂閱topic

  3. 最后就是通過topic推送消息熬粗,接收消息

一步一步講:

第一步搀玖,與服務(wù)器建立連接

??先丟代碼,然后看注釋:

private void initPush() {
        // 服務(wù)器地址(協(xié)議+地址+端口號)
        String uri = host;
        client = new MqttAndroidClient(this, uri, clientId);
        // 設(shè)置MQTT監(jiān)聽并且接受消息
        client.setCallback(mqttCallback);
        //Mqtt的一些設(shè)置
        conOpt = new MqttConnectOptions();
        conOpt.setAutomaticReconnect(true);
        // 清除緩存
        conOpt.setCleanSession(true);
        // 設(shè)置超時時間驻呐,單位:秒
        conOpt.setConnectionTimeout(10);
        // 心跳包發(fā)送間隔灌诅,單位:秒
        conOpt.setKeepAliveInterval(20);
        myTopic = String.format(TOPIC_SUB, mDeviceId);
        Log.e(TAG,"myTopic_________"+myTopic);
        doClientConnection();
    }

??上面的這些參數(shù),我碰到了兩個問題含末。

??上面的這些參數(shù)猜拾,我碰到了兩個問題。

??上面的這些參數(shù)答渔,我碰到了兩個問題关带。

  1. 第一個問題侥涵,與服務(wù)器建立連接沼撕,你得先有一個服務(wù)器吧?我根據(jù)網(wǎng)上的步驟芜飘,創(chuàng)建了一個apache-apollo服務(wù)器务豺,并且啟動了,也啟動成功了嗦明,我建立連接的時候笼沥,總是失敗。然后娶牌,找啊找奔浅,找啊找。問題沒有解決诗良,但是汹桦,我找到了一個可以用的服務(wù)器,也就是這里的uri鉴裹,不要設(shè)置MqttConnectOptions的用戶名和密碼舞骆,設(shè)置了他會拒絕
private String host = "tcp://test.mosquitto.org:1883";
  1. 第二個問題,我連接成功之后径荔,不一會督禽,他就會自動斷開連接,或者总处,推送完消息之后狈惫,他就會斷開連接。然后鹦马,網(wǎng)上搜原因胧谈,找啊找玖院,誒,我找到了第岖。MqttAndroidClient的構(gòu)造方法:
/**
     * Constructor - create an MqttAndroidClient that can be used to communicate with an MQTT server on android
     * 
     * @param context 
     *            object used to pass context to the callback. 
     * @param serverURI
     *            specifies the protocol, host name and port to be used to
     *            connect to an MQTT server
     * @param clientId
     *            specifies the name by which this connection should be
     *            identified to the server
     */
    public MqttAndroidClient(Context context, String serverURI,
            String clientId) {
        this(context, serverURI, clientId, null, Ack.AUTO_ACK);
    }

看第三個參數(shù)难菌,clientId,指定一個名字蔑滓,用來連接服務(wù)器的身份標識郊酒。就是說,你設(shè)置的這個值键袱,是你在服務(wù)器的唯一標識燎窘,不能跟其他用戶的相同。我把這個clientId直接用uuid生成蹄咖,就沒問題了褐健。

第二步,訂閱topic

??回到上面澜汤,接著往下面走蚜迅,

/**
     * 連接MQTT服務(wù)器
     */
    private void doClientConnection() {
        if (!client.isConnected() && isConnectIsNormal()) {
            try {
                client.connect(conOpt, null, iMqttActionListener);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

    }
    
    /**
     * 判斷網(wǎng)絡(luò)是否連接
     */
    private boolean isConnectIsNormal() {
        ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager != null) {
            NetworkInfo info = connectivityManager.getActiveNetworkInfo();
            if (info != null && info.isAvailable()) {
                String name = info.getTypeName();
                Log.e(TAG, "MQTT當前網(wǎng)絡(luò)名稱:" + name);
                return true;
            } else {
                Log.e(TAG, "MQTT 沒有可用網(wǎng)絡(luò)");
                return false;
            }
        } else {
            return false;
        }
    }

??這個方法就是用來連接服務(wù)器的,首先判斷是否正在連接俊抵,后面那個是判斷當前有沒有網(wǎng)絡(luò)谁不。再就是這個iMqttActionListener監(jiān)聽了

// MQTT是否連接成功
    private IMqttActionListener iMqttActionListener = new IMqttActionListener() {

        @Override
        public void onSuccess(IMqttToken arg0) {
            Log.e(TAG, "連接成功 ");
            try {
                // 訂閱myTopic話題
                client.subscribe(myTopic, 0);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            Log.e(TAG, "連接失敗");
            arg1.printStackTrace();
            // 連接失敗,重連
        }
    };

??訥徽诲,就是這里刹帕,你如果服務(wù)器有問題,他一直走onFailure方法谎替。服務(wù)器連接成功之后偷溺,就是訂閱topic。我來說說這個

client.subscribe(myTopic, 0);

??首先钱贯,這個主題挫掏,是你自己跟服務(wù)器商量好的,隨便什么都可以喷舀。為什么要訂閱主題呢砍濒?我提前給你瞅瞅推送消息是怎么推送的

??第二個參數(shù),消息的類型qos硫麻,有三種:0爸邢、1、2

  1. 0代表“至多一次”拿愧,消息發(fā)布完全依賴底層 TCP/IP 協(xié)議杠河。會發(fā)生消息丟失或重復。這一級別可用于如下情況,環(huán)境傳感器數(shù)據(jù)券敌,丟失一次讀記錄無所謂唾戚,因為不久后還會有第二次發(fā)送
  2. 1代表“至少一次”,確保消息到達待诅,但消息重復可能會發(fā)生
  3. 2代表“只有一次”叹坦,確保消息到達一次。這一級別可用于如下情況卑雁,在計費系統(tǒng)中募书,消息重復或丟失會導致不正確的結(jié)果。

??簡單說明下测蹲,如果發(fā)送的是臨時的消息莹捡,例如給某topic所有在線的設(shè)備發(fā)送一條消息,丟失的話也無所謂扣甲,0就可以了篮赢。如果需要客戶端保證能接收消息,需要指定QoS為1

client.publish(topic, new MqttMessage(msg.getBytes()));

??訥琉挖,推送消息启泣,是根據(jù)topic推送的,第二個參數(shù)粹排,就是你要推送的具體消息种远。我個人認為涩澡,你可以理解成就類似于鍵值對的形式顽耳,

不同的用戶可以訂閱相同的主題

不同的用戶可以訂閱相同的主題

不同的用戶可以訂閱相同的主題

??這個就是跟其他長連接不同的地方,底層妙同,其實都一樣射富,雖然我沒有看底層的代碼。想也想的到粥帚,服務(wù)器肯定是根據(jù)這個主題胰耗,去找對應(yīng)的用戶,然后推送消息芒涡。而其他的長連接就是直接指定用戶柴灯。跑題了,跑題了费尽。

第三步赠群,推送、接收消息

??當你連接服務(wù)器成功之后旱幼,就要推送消息了查描,我用的EventBus發(fā)的

private void publishData(String msg) {
        String topic = myTopic;
        try {
            Log.e(TAG,"給__"+topic+"__topic發(fā)送的消息為:"+msg);
            client.publish(topic, new MqttMessage(msg.getBytes()));
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
    
    // MQTT監(jiān)聽并且接受消息
    private MqttCallback mqttCallback = new MqttCallback() {

        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {
            Log.e(TAG,"接受到__"+topic+"__topic的消息為:"+new String(message.getPayload()));
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {
            Log.e(TAG,"deliveryComplete");
        }

        @Override
        public void connectionLost(Throwable arg0) {
            // 失去連接,重連
            Log.e(TAG,"失去連接");
        }
    };

??當你的clientId重復的時候,他就會一直走connectionLost方法冬三。到這里匀油,基本上就講完了,要注意的是勾笆,退出的時候敌蚜,記得要釋放資源

@Override
    public void onDestroy() {
        try {
            if (client != null && client.isConnected()) {
                client.disconnect();
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }

網(wǎng)上很多都是直接講整體流程,重來不講中間碰到的問題窝爪。難受

項目鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钝侠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子酸舍,更是在濱河造成了極大的恐慌帅韧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啃勉,死亡現(xiàn)場離奇詭異忽舟,居然都是意外死亡,警方通過查閱死者的電腦和手機淮阐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門叮阅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泣特,你說我怎么就攤上這事浩姥。” “怎么了状您?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵勒叠,是天一觀的道長。 經(jīng)常有香客問我膏孟,道長眯分,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任柒桑,我火速辦了婚禮弊决,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘魁淳。我一直安慰自己飘诗,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布界逛。 她就那樣靜靜地躺著昆稿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪仇奶。 梳的紋絲不亂的頭發(fā)上貌嫡,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天比驻,我揣著相機與錄音,去河邊找鬼岛抄。 笑死别惦,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的夫椭。 我是一名探鬼主播掸掸,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蹭秋!你這毒婦竟也來了扰付?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤仁讨,失蹤者是張志新(化名)和其女友劉穎羽莺,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洞豁,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡盐固,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了丈挟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刁卜。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖曙咽,靈堂內(nèi)的尸體忽然破棺而出蛔趴,到底是詐尸還是另有隱情,我是刑警寧澤例朱,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布孝情,位于F島的核電站,受9級特大地震影響茉继,放射性物質(zhì)發(fā)生泄漏咧叭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一烁竭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吉挣,春花似錦派撕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至氯哮,卻和暖如春际跪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工姆打, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留良姆,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓幔戏,卻偏偏與公主長得像玛追,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子闲延,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容