Smack 4.1.9(一)初始化仿畸、注冊食棕、登錄、登出错沽、注銷

前言

Smack官方地址
即時通訊的項目用到Smack 4.1.9版本簿晓,由于項目需求Smack某些API不符合要求,有些需求采用自己后臺接口實現(xiàn)千埃,例如:文件上傳憔儿、文件下載、注冊放可、添加好友谒臼,刪除好友,好友列表吴侦、用戶詳情屋休、群列表、群成員备韧、查詢離線消息劫樟、查詢歷史消息、離開群织堂,這樣做的好處可以做到業(yè)務(wù)與IM分離叠艳,用戶關(guān)系可以從其他系統(tǒng)導(dǎo)入直接使用,并且后面也還存在Pjsip的用戶體系易阳。

項目坑

項目里面最坑就是斷線之后聊天室要重新加入才能收到消息附较,Smack 4.2.0修復(fù)了這個bug,斷線之后不需要重新加入聊天室(群)潦俺, [SMACK-572] - Rejoin MUC rooms after reconnect拒课。

服務(wù)器做時間校驗存在后臺返回報文格式不對,無法正常進(jìn)行時間校驗(浪費兩天找這個問題)事示,升級成4.1.9解決這個問題早像,本來想用最新版本但是里面有些API的用法發(fā)生改變也就沒用了,建議用Smack最新版本肖爵,可以避免很多麻煩卢鹦。
[SMACK-716] - EntityTimeManager.getTime() does not set the recipients JID

代碼

Android Studio build.gradle依賴:

    //smack依賴包
    compile 'org.igniterealtime.smack:smack-android-extensions:4.1.9'
    compile 'org.igniterealtime.smack:smack-android:4.1.9'
    compile 'org.igniterealtime.smack:smack-tcp:4.1.9'
    compile 'org.igniterealtime.smack:smack-im:4.1.9'
  • 初始化

這里只做一個簡單的Smack初始化,數(shù)據(jù)加密可能還涉及到證書生成劝堪、添加校驗冀自。具體證書的生成可以參看這篇博客TLS 雙向認(rèn)證揉稚,即時通訊項目涉及到用戶切換,所以設(shè)計XMPP流每個用戶都重新初始化熬粗,否則用戶退出后搀玖,切換到新用戶存在各種問題。

    try {
            KeyStore trustStore = KeyStore.getInstance("JKS");
            trustStore.load(getClass().getResourceAsStream("/truststore"), storePass.toCharArray());
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(trustStore);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), null);
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        //初始化xmpp流
        XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
                .setServiceName(URConstant.xmppIp)
                .setHost(URConstant.xmppIp)
                .setPort(URConstant.xmppPort)
                // 添加服務(wù)器域名荐糜、IP巷怜、端口  
                // 域名可以跟IP一樣
                //.setServiceName("applexmpp.com")
                //.setHost("172.19.26.12")
                //.setPort(5222)
                .setSecurityMode(ConnectionConfiguration.SecurityMode.ifpossible)
                 //設(shè)置為true,利于開發(fā)調(diào)試
                .setDebuggerEnabled(options.getDebuggerEnabled())
                .setConnectTimeout(options.getConnectTimeout())
                 //添加證書
                // .setCustomSSLContext(sslContext)
                // .setHostnameVerifier()
                .setCompressionEnabled(true)
                .build();
    connection = new XMPPTCPConnection(config);
  • 注冊
 /**
     * 注冊
     *
     * @param account  注冊帳號
     * @param password 注冊密碼
     * @return true 注冊成功 false 注冊失敗
     */
    public boolean register(String account, String password) {
        try {
            if (!connection.isConnected()) {
                connection.connect();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        try {
            AccountManager.getInstance(connection).createAccount(account, password);
        } catch (XMPPException | SmackException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
  • 登陸

其中出現(xiàn)的一些異潮┦希可以做一接口回調(diào)反饋給UI層

 /**
     * 登錄tigase服務(wù)器
     *
     * @param userName 用戶名
     * @param pwd      密碼
     */
    public void loginTigase(String userName, String pwd) {
        try {
            if (!connection.isConnected()) {
                connection.connect();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        if (connection.isConnected()) {
            try {
                connection.login(userName, pwd, "android");
                if (connection.isAuthenticated()) {                  
                    // 允許自動連接
                    ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
                    // 重聯(lián)間隔5秒
                    reconnectionManager.setFixedDelay(5);
                    reconnectionManager.enableAutomaticReconnection();//開啟重聯(lián)機(jī)制

                    // 維持ping
                    PingManager.setDefaultPingInterval(10);
                    PingManager pingManager = PingManager.getInstanceFor(connection);
                    // 監(jiān)聽連接狀態(tài)
                    pingManager.registerPingFailedListener(connectListener);

                    //獲取、校驗服務(wù)器時間
                    TimeInfo.checkServerIntervalTime(connection);
                } else {
                }
            } catch (XMPPException | IOException e) {
                e.printStackTrace();
            } catch (SmackException e) {
                e.printStackTrace();
            }
        } else {
        }
    }

時間校驗工具類

public class TimeInfo {
    private static long serverIntervalTime;
     /**
      * 獲取本地時間與服務(wù)器的時間差绣张,用于消息時間驗證
     */
    public static long checkServerIntervalTime(XMPPTCPConnection connection) {
        final EntityTimeManager timeManager = EntityTimeManager.getInstanceFor(connection);
        EntityTimeManager.setAutoEnable(true);
        try {
            String utcTime = timeManager.getTime(URConstant.xmppIp).getUtc();
            //返回時區(qū)
            String tzo = timeManager.getTime(URConstant.xmppIp).getTzo();
            long serverTime = utc2Local(utcTime, tzo);
            return serverTime - System.currentTimeMillis();
        } catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException e) {
            e.printStackTrace();
           return 0;
        }
    }

    /**
     * 函數(shù)功能描述:UTC時間轉(zhuǎn)本地時間格式
     *
     * @param utcTime UTC時間格式
     * @param pysj    時區(qū)
     * @return 本地時間格式的時間
     * eg:utc2Local("2017-06-14 09:37:50.788+08:00", "yyyy-MM-dd HH:mm:ss.SSSXXX", "yyyy-MM-dd HH:mm:ss.SSS")
     */

    public static long utc2Local(String utcTime, String pysj) {
        @SuppressLint("SimpleDateFormat")
        SimpleDateFormat utcFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");//UTC時間格式
        utcFormater.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date gpsUTCDate = null;
        try {
            gpsUTCDate = utcFormater.parse(utcTime);
        } catch (ParseException e) {
            e.printStackTrace();
            return System.currentTimeMillis();
        }
        @SuppressLint("SimpleDateFormat")
        SimpleDateFormat localFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//當(dāng)?shù)貢r間格式
        localFormater.setTimeZone(TimeZone.getTimeZone("GMT" + pysj));
        String localTime = localFormater.format(gpsUTCDate.getTime());
        Date date;
        try {
            date = localFormater.parse(localTime);
        } catch (ParseException e) {
            e.printStackTrace();
            return System.currentTimeMillis();
        }
        return date.getTime();
    }
}
  • 登出
     /**
     * XMPP登出  將流置為空答渔,新用戶重新初始化
     */
    public void logOut() {
        URLog.d("XMPPConnectionManager 退出登陸");
        //這里需要先將登陸狀態(tài)改變?yōu)椤半x線”,再斷開連接侥涵,不然在后臺還是上線的狀態(tài)
        Presence presence = new Presence(Presence.Type.unavailable);
        try {
            connection.sendPacket(presence);
            if (connection != null) {
                connection.disconnect();
                connection = null;
            }
        } catch (SmackException.NotConnectedException e) {
            e.printStackTrace();
        }
    }

*注銷


    /**
     * 注銷前用戶登錄
     *
     * @return
     */
    private boolean deleteUser() {
        try {
            try {
                if (!connection.isConnected()) {
                    connection.connect();
                }
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            AccountManager.getInstance(connection).deleteAccount();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

感悟

這個項目讓我知道日志的重要性沼撕,熟悉XMPP協(xié)議報文是非常必要的,要不然出現(xiàn)問題了就是一臉懵逼不知道從哪排查起芜飘。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末务豺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嗦明,更是在濱河造成了極大的恐慌笼沥,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娶牌,死亡現(xiàn)場離奇詭異奔浅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)诗良,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門汹桦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鉴裹,你說我怎么就攤上這事舞骆。” “怎么了径荔?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵督禽,是天一觀的道長。 經(jīng)常有香客問我猖凛,道長赂蠢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任辨泳,我火速辦了婚禮虱岂,結(jié)果婚禮上玖院,老公的妹妹穿的比我還像新娘。我一直安慰自己第岖,他們只是感情好难菌,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蔑滓,像睡著了一般郊酒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上键袱,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天燎窘,我揣著相機(jī)與錄音,去河邊找鬼蹄咖。 笑死褐健,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的澜汤。 我是一名探鬼主播蚜迅,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼俊抵!你這毒婦竟也來了谁不?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤徽诲,失蹤者是張志新(化名)和其女友劉穎刹帕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體馏段,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡轩拨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了院喜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亡蓉。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖喷舀,靈堂內(nèi)的尸體忽然破棺而出砍濒,到底是詐尸還是另有隱情,我是刑警寧澤硫麻,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布爸邢,位于F島的核電站,受9級特大地震影響拿愧,放射性物質(zhì)發(fā)生泄漏杠河。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望券敌。 院中可真熱鬧唾戚,春花似錦、人聲如沸待诅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卑雁。三九已至募书,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間测蹲,已是汗流浹背莹捡。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留扣甲,地道東北人道盏。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像文捶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子媒咳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

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

  • 一粹排、Smack庫概述 ????Smack是一個開源、易用的XMPP/Jabber客戶端庫涩澡,它使用Java語言開發(fā)顽耳,...
    AndryYu閱讀 6,128評論 2 13
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,180評論 25 707
  • 因為有愛,即使再痛苦的記憶妙同,也不能選擇忘記射富。
    簡單粗暴就行閱讀 186評論 0 0
  • 為什么別人已經(jīng)在市中心買了房芒涡,還有一輛進(jìn)口車柴灯,而我還在租著五環(huán)外的地下室,每天擠了兩個小時的地鐵去上班费尽?為什么別人...
    涼樹姑娘閱讀 241評論 0 2
  • 6月14日 晴 老林叔赠群、艷陽天和我三人是早上六時三十分出發(fā)的,途徑大耿峪進(jìn)入白楊岔旱幼。七時二十五分開始徒步...
    鄧文偉閱讀 1,536評論 0 1