你還在用第三方的框架實現(xiàn)聊天和消息推送?快快試試吧
Socket.IO(官網(wǎng))介紹
是一個跨平臺的聊天框架董栽,可以實現(xiàn) web 端和移動端的實時聊天企孩,簡單說就是用來做聊天和消息推送的勿璃。最初以為項目做消息推送會直接使用第三方的推汽,比如小米歹撒、極光啥的暖夭,但是撵孤,架構(gòu)師說我們不用第三方的邪码,自己要搭建消息推送咬清,Socket.io技術(shù)很成熟了旧烧。所以就這樣開始了Socket.io的學習之路掘剪。第一次接觸Socket.io以為很難做,因為不了解肆汹,加上能找的資源有限(上網(wǎng)查找的都是英文資料昂勉,有關(guān)于Android端的Socke.io更是少之又少扫腺,除非你去stackoverflow里面去找笆环,英語還得好)躁劣,所以寫篇文章記錄下實現(xiàn)該功能流程以及遇到的問題。
官方Demo志膀,Github的Demo溉浙,這兩個 demo 都是一個聊天室蒋荚,可以在里面聊天,剛開始弄這個的時候發(fā)現(xiàn)有好多哥們在那里期升,還找?guī)讉€一起在做聊天功能的小伙伴,快快下載試試吧吨铸。
本文不說服務(wù)端的搭建和web端的實現(xiàn)祖秒,只是來說說 Android 端如何使用Socket.io實現(xiàn)消息推送功能竭缝。
(1)導包
Android Studio
導包抬纸,一共有兩種情況(PS: Eclipse
用戶也不要哭,下面會教你怎樣獲取到 JAR
)
第一種情況
compile 'com.github.nkzawa:socket.io-client:0.3.0'
-
第二種情況
compile ('io.socket:socket.io-client:0.7.0') { // excluding org.json which is provided by Android exclude group: 'org.json', module: 'json' }
注意:兩個包的區(qū)別,如果你的項目沒有用到 Https
,那么你可以使用兩個當中的一個脖阵。如果有用到 Https
墅茉,那么你就要用二個包就斤,不然你會連接不上 Https
的,具體的連接方式坠宴,以下會介紹啄踊。
第一種情況的導包獲取到的 JAR
形式
第二種情況的導包獲取到的 JAR
形式
PS: Android Studio
用戶直接跳過(如果你想看看你的Studio下載的 JAR
放在那里也可以看看)址晕。Eclipse
用戶獲取 Jar
,如果你會去遠程倉庫下載 Jar
启搂,那么你就去吧胳赌,也就是幾個 JAR
而已疑苫,不然的話你還是得借助 Android Studio
來獲取 Jar
。
用Studio導入包后找到你的
External Libraries
,選中你的 JAR 撼短,如engine.io-client-0.7.0
點擊右鍵曲横,點擊Library Properties
,會彈出一個對話框不瓶,Copy 這個URL蚊丐,打開我的電腦
吠撮,粘貼到導航欄點擊確定就可以看到你的JAR
了泥兰,但是,這個JAR
是一個資源文件的JAR
,里面有源碼的膀捷,我們不需要這個,點擊back后退削彬,一般會有三個文件夾全庸,其中的一個就是你需要的JAR
了。流程圖如下:
(2)代碼使用
導完包剩下的就是代碼的使用了融痛。由于 Socket.io
封裝得很好壶笼,所以我們能用到的類和方法不多,也就幾個而已雁刷。
- 獲取
Socket
和設(shè)置 url :mSocket = IO.socket( "http://192.168.205.125:10443" );
- 連接
mSocket.mSocket.connect();
覆劈。 - 發(fā)送消息
mSocket.emit( "newMessage", data );
,這里需要注意的是: data 是JSONObject
的類责语。 - 消息監(jiān)聽
mSocket.on( Socket.EVENT_CONNECT, onConnect );// 連接成功
- 斷開連接
mSocket.disconnect();
炮障。 - 斷開消息監(jiān)聽
mSocket.off( Socket.EVENT_CONNECT, onConnect );
就是這么幾個方法就可以實現(xiàn)消息推送或者實現(xiàn)聊天了。由于本文主要是實現(xiàn)消息推送的功能坤候,所以把主要的代碼放在了 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", "小王" ); // 這里一般是設(shè)置登錄名
mSocket.emit( "loginName", jsonObject ); // 發(fā)送登錄人
} 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 );// 監(jiān)聽消息事件回調(diào)
}
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 );// 監(jiān)聽消息事件回調(diào)
}
private Emitter.Listener onConnectMsg = new Emitter.Listener() {
@Override
public void call( final Object... args ) {
// 在這里處理你的消息
Log.e( TAG, "服務(wù)器返回來的消息 : " + args[0] );
}
};
/**
* 實現(xiàn)消息回調(diào)接口
*/
private Emitter.Listener onConnect = new Emitter.Listener() {
@Override
public void call( final Object... args ) {
Log.e( TAG, "連接成功 " + args[0] );
if (!isConnected) { // 如果已經(jīng)斷開智末,重新發(fā)送
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put( "userName", "小王" ); // 這里一般是設(shè)置登錄名
mSocket.emit( "loginName", jsonObject ); // 發(fā)送登錄人
} 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;
}
}
就這樣完成了一個消息推送,不需要集成什么東西遍蟋,也不用受制于人吹害。