Socket.io

Socket.IO(官網)介紹

是一個跨平臺的聊天框架,能夠實現 web 端和移動端的實時聊天,簡單說就是用來作聊天和消息推送的。最初覺得項目作消息推送會直接使用第三方的,好比小米、極光啥的,可是,架構師說咱們不用第三方的,本身要搭建消息推送,Socket.io技術很成熟了。因此就這樣開始了Socket.io的學習之路。第一次接觸Socket.io覺得很難作,由於不瞭解,加上能找的資源有限(上網查找的都是英文資料,有關於Android端的Socke.io更是少之又少,除非你去stackoverflow裏面去找,英語還得好),因此寫篇文章記錄下實現該功能流程以及遇到的問題。
官方DemoGithub的Demo,這兩個 demo 都是一個聊天室,能夠在裏面聊天,剛開始弄這個的時候發現有好多哥們在那裏,還找幾個一塊兒在作聊天功能的小夥伴,快快下載試試吧。java

本文不說服務端的搭建和web端的實現,只是來講說 Android 端如何使用Socket.io實現消息推送功能。

(1)導包

Android Studio 導包,一共有兩種狀況(PS: Eclipse 用戶也不要哭,下面會教你怎樣獲取到 JARandroid

  1. 第一種狀況 compile 'com.github.nkzawa:socket.io-client:0.3.0'git

  2. 第二種狀況github

    compile ('io.socket:socket.io-client:0.7.0') { // excluding org.json which is provided by Android exclude group: 'org.json', module: 'json' } 

注意:兩個包的區別,若是你的項目沒有用到 Https ,那麼你可使用兩個當中的一個。若是有用到 Https ,那麼你就要用二個包,否則你會鏈接不上 Https 的,具體的鏈接方式,如下會介紹。web

第一種狀況的導包獲取到的 JAR 形式json

 
 

第二種狀況的導包獲取到的 JAR 形式服務器

 
 

PSAndroid Studio 用戶直接跳過(若是你想看看你的Studio下載的 JAR 放在那裏也能夠看看)。Eclipse 用戶獲取 Jar,若是你會去遠程倉庫下載 Jar,那麼你就去吧,也就是幾個 JAR 而已,否則的話你仍是得藉助 Android Studio 來獲取 Jarwebsocket

用Studio導入包後找到你的 External Libraries ,選中你的 JAR ,如 engine.io-client-0.7.0 點擊右鍵,點擊 Library Properties ,會彈出一個對話框,Copy 這個URL,打開個人電腦,粘貼到導航欄點擊肯定就能夠看到你的 JAR了,可是,這個 JAR 是一個資源文件的 JAR ,裏面有源碼的,咱們不須要這個,點擊back後退,通常會有三個文件夾,其中的一個就是你須要的 JAR了。流程圖以下:架構

 
 

 
 

 
 

(2)代碼使用

導完包剩下的就是代碼的使用了。因爲 Socket.io 封裝得很好,因此咱們能用到的類和方法很少,也就幾個而已。app

  • 獲取 Socket 和設置 url : mSocket = IO.socket( "http://192.168.205.125:10443" );
  • 鏈接 mSocket.mSocket.connect();
  • 發送消息 mSocket.emit( "newMessage", data );,這裏須要注意的是: data 是 JSONObject 的類。
  • 消息監聽 mSocket.on( Socket.EVENT_CONNECT, onConnect );// 鏈接成功
  • 斷開鏈接 mSocket.disconnect();
  • 斷開消息監聽 mSocket.off( Socket.EVENT_CONNECT, onConnect );

就是這麼幾個方法就能夠實現消息推送或者實現聊天了。因爲本文主要是實現消息推送的功能,因此把主要的代碼放在了 Service,順便把流程寫一下,方便初學者學習。

import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; import java.net.URISyntaxException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import io.socket.client.IO; import io.socket.client.Socket; import io.socket.emitter.Emitter; public class MessagePushService extends Service { private static final String TAG = MessagePushService.class.getSimpleName(); private Socket mSocket; private boolean isConnected; /** * 初始化Socket,Https的鏈接方式 */ private void initSocketHttps() { SSLContext sc = null; TrustManager[] trustCerts = new TrustManager[] { new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkServerTrusted( X509Certificate[] chain, String authType ) throws CertificateException { } @Override public void checkClientTrusted( X509Certificate[] chain, String authType ) throws CertificateException { } } }; try { sc = SSLContext.getInstance( "TLS" ); sc.init( null, trustCerts, null ); IO.Options opts = new IO.Options(); opts.sslContext = sc; opts.hostnameVerifier = new HostnameVerifier() { @Override public boolean verify( String s, SSLSession sslSession ) { return true; } }; mSocket = IO.socket( "https://192.168.205.125:10443", opts ); } catch ( NoSuchAlgorithmException e ) { e.printStackTrace(); } catch ( KeyManagementException e ) { e.printStackTrace(); } catch ( URISyntaxException e ) { e.printStackTrace(); } } /** * 初始化Socket,Http的鏈接方式 */ private void initSocketHttp() { try { mSocket = IO.socket( "http://192.168.205.125:10443" ); // 初始化Socket } catch ( URISyntaxException e ) { e.printStackTrace(); } } private void connectSocket() { try { mSocket.connect(); JSONObject jsonObject = new JSONObject(); jsonObject.put( "userName", "小王" ); // 這裏通常是設置登陸名 mSocket.emit( "loginName", jsonObject ); // 發送登陸人 } catch ( JSONException e ) { e.printStackTrace(); } mSocket.on( Socket.EVENT_CONNECT, onConnect );// 鏈接成功 mSocket.on( Socket.EVENT_DISCONNECT, onDisconnect );// 斷開鏈接 mSocket.on( Socket.EVENT_CONNECT_ERROR, onConnectError );// 鏈接異常 mSocket.on( Socket.EVENT_CONNECT_TIMEOUT, onConnectTimeoutError );// 鏈接超時 mSocket.on( "newMessage", onConnectMsg );// 監聽消息事件回調 } private void disConnectSocket() { mSocket.disconnect(); mSocket.off( Socket.EVENT_CONNECT, onConnect );// 鏈接成功 mSocket.off( Socket.EVENT_DISCONNECT, onDisconnect );// 斷開鏈接 mSocket.off( Socket.EVENT_CONNECT_ERROR, onConnectError );// 鏈接異常 mSocket.off( Socket.EVENT_CONNECT_TIMEOUT, onConnectTimeoutError );// 鏈接超時 mSocket.off( "newMessage", onConnectMsg );// 監聽消息事件回調 } private Emitter.Listener onConnectMsg = new Emitter.Listener() { @Override public void call( final Object... args ) { // 在這裏處理你的消息 Log.e( TAG, "服務器返回來的消息 : " + args[0] ); } }; /** * 實現消息回調接口 */ private Emitter.Listener onConnect = new Emitter.Listener() { @Override public void call( final Object... args ) { Log.e( TAG, "鏈接成功 " + args[0] ); if (!isConnected) { // 若是已經斷開,從新發送 try { JSONObject jsonObject = new JSONObject(); jsonObject.put( "userName", "小王" ); // 這裏通常是設置登陸名 mSocket.emit( "loginName", jsonObject ); // 發送登陸人 } catch ( JSONException e ) { e.printStackTrace(); } isConnected = true; } } }; private Emitter.Listener onDisconnect = new Emitter.Listener() { @Override public void call( Object... args ) { Log.e( TAG, "斷開鏈接 " + args[0] ); isConnected = false; } }; private Emitter.Listener onConnectError = new Emitter.Listener() { @Override public void call( final Object... args ) { Log.e( TAG, "鏈接 失敗" + args[0] ); } }; private Emitter.Listener onConnectTimeoutError = new Emitter.Listener() { @Override public void call( final Object... args ) { Log.e( TAG, "鏈接 超時" + args[0] ); } }; @Nullable @Override public IBinder onBind( Intent intent ) { return null; } } 

就這樣完成了一個消息推送,不須要集成什麼東西,也不用受制於人。

總結:剛開始作這個的時候找不到各類 JAR (項目仍是在使用Eclipse開發中,因此仍是須要去找到 JAR),那會本身才倒騰 Android Studio 沒多久,把 Demo 下載下來運行沒問題,而後就去找 這個資源的 JAR,準備集成到 項目裏面去,一開始覺得只要 engine.io-client JAR 和 socket.io-client JAR ,結果就報錯了,而後不斷的查資料找包(這時候還不知道 Android Studio 已經把JAR 下載到電腦了),最後才知道 Android Studio 下載的JAR在哪裏(這纔有了前面的找JAR),等到全部的JAR找到後,集成到了項目裏面去,最後仍是不斷的報 NoClassDefFoundError ,把這些JAR所有放到 Android Studio 集成運行卻沒有問題,這才發現是個人 Eclipse 問題,等找到這些緣由,時間已通過去兩天了,悲劇呀,而後快速的集成到項目,最終運行一切Ok啦!可是,若是你以爲故事就這樣沒了,那就太沒意思了,這個時候公司的接口所有轉成 https ,悲劇呀,項目運行不起來了。花時間找源碼,看看怎樣實現,最終在stackoverflow找到了關於加載證書的方式,可是翻源碼的時候卻發現沒有這個 opts.hostnameVerifier 屬性,再一次悲劇(這個時候,我用的是上面的第一種JAR,也就是官網介紹的: compile 'com.github.nkzawa:socket.io-client:0.3.0')。這個時候時候發現了 Socket.io 官網的介紹和 Github 的介紹是兩種不一樣的 JAR,最後導入 githubJAR(第二種導包方式,因此你仍是直接用這個包吧) 確實能夠運行了。滿滿的坑呀!

做者:xiaowen_2010 連接:https://www.jianshu.com/p/274db90fa0be 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索