是一個跨平臺的聊天框架,能夠實現 web 端和移動端的實時聊天,簡單說就是用來作聊天和消息推送的。最初覺得項目作消息推送會直接使用第三方的,好比小米、極光啥的,可是,架構師說咱們不用第三方的,本身要搭建消息推送,Socket.io技術很成熟了。因此就這樣開始了Socket.io的學習之路。第一次接觸Socket.io覺得很難作,由於不瞭解,加上能找的資源有限(上網查找的都是英文資料,有關於Android端的Socke.io更是少之又少,除非你去stackoverflow裏面去找,英語還得好),因此寫篇文章記錄下實現該功能流程以及遇到的問題。
官方Demo,Github的Demo,這兩個 demo 都是一個聊天室,能夠在裏面聊天,剛開始弄這個的時候發現有好多哥們在那裏,還找幾個一塊兒在作聊天功能的小夥伴,快快下載試試吧。java
Android Studio
導包,一共有兩種狀況(PS: Eclipse
用戶也不要哭,下面會教你怎樣獲取到 JAR
)android
第一種狀況 compile 'com.github.nkzawa:socket.io-client:0.3.0'
git
第二種狀況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
形式服務器
PS: Android Studio
用戶直接跳過(若是你想看看你的Studio下載的 JAR
放在那裏也能夠看看)。Eclipse
用戶獲取 Jar
,若是你會去遠程倉庫下載 Jar
,那麼你就去吧,也就是幾個 JAR
而已,否則的話你仍是得藉助 Android Studio
來獲取 Jar
。websocket
用Studio導入包後找到你的
External Libraries
,選中你的 JAR ,如engine.io-client-0.7.0
點擊右鍵,點擊Library Properties
,會彈出一個對話框,Copy 這個URL,打開個人電腦
,粘貼到導航欄點擊肯定就能夠看到你的JAR
了,可是,這個JAR
是一個資源文件的JAR
,裏面有源碼的,咱們不須要這個,點擊back後退,通常會有三個文件夾,其中的一個就是你須要的JAR
了。流程圖以下:架構
導完包剩下的就是代碼的使用了。因爲 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; } }
就這樣完成了一個消息推送,不須要集成什麼東西,也不用受制於人。
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,最後導入 github
的 JAR
(第二種導包方式,因此你仍是直接用這個包吧) 確實能夠運行了。滿滿的坑呀!