溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

OkSocket與Android怎么用

發(fā)布時間:2021-08-09 10:44:03 來源:億速云 閱讀:144 作者:小新 欄目:移動開發(fā)

這篇文章給大家分享的是有關(guān)OkSocket與Android怎么用的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

OkSocket簡介

Android OkSocket是一款基于阻塞式傳統(tǒng)Socket的一款Socket客戶端整體解決方案.您可以使用它進(jìn)行簡單的基于Tcp協(xié)議的Socket通訊,當(dāng)然,也可以進(jìn)行大數(shù)據(jù)量復(fù)雜的Socket通訊,
支持單工,雙工通訊.

Maven配置

OkSocket 目前僅支持 JCenter 倉庫

allprojects {
  repositories {
    jcenter()
  }
}

在Module的build.gradle文件中添加依賴配置

dependencies {
  compile 'com.tonystark.android:socket:1.0.0'
}

參數(shù)配置

在AndroidManifest.xml中添加權(quán)限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

混淆配置

請避免混淆OkSocket,在Proguard混淆文件中增加以下配置:

-dontwarn com.xuhao.android.libsocket.**
-keep class com.xuhao.android.socket.impl.abilities.** { *; }
-keep class com.xuhao.android.socket.impl.exceptions.** { *; }
-keep class com.xuhao.android.socket.impl.EnvironmentalManager { *; }
-keep class com.xuhao.android.socket.impl.BlockConnectionManager { *; }
-keep class com.xuhao.android.socket.impl.UnBlockConnectionManager { *; }
-keep class com.xuhao.android.socket.impl.SocketActionHandler { *; }
-keep class com.xuhao.android.socket.impl.PulseManager { *; }
-keep class com.xuhao.android.socket.impl.ManagerHolder { *; }
-keep class com.xuhao.android.socket.interfaces.** { *; }
-keep class com.xuhao.android.socket.sdk.** { *; }
# 枚舉類不能被混淆
-keepclassmembers enum * {
  public static **[] values();
  public static ** valueOf(java.lang.String);
}
-keep class com.xuhao.android.socket.sdk.OkSocketOptions$* {
  *;
}

OkSocket初始化

將以下代碼復(fù)制到項目Application類onCreate()中,OkSocket會為自動檢測環(huán)境并完成配置:

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    //在主進(jìn)程初始化一次,多進(jìn)程時需要區(qū)分主進(jìn)程.
    OkSocket.initialize(this);
    //如果需要開啟Socket調(diào)試日志,請配置
    //OkSocket.initialize(this,true);
  }
}

調(diào)用演示

測試服務(wù)器

該服務(wù)器是專門為初學(xué)者調(diào)試 OkSocket 庫部屬的一臺測試服務(wù)器,初學(xué)者可以將項目中的 app 安裝到手機上,點擊 Connect 按鈕即可,該服務(wù)器僅為熟悉通訊方式和解析方式使用.該服務(wù)器不支持心跳返回,不能作為商用服務(wù)器.服務(wù)器代碼在 SocketServerDemo 文件夾中,請注意參考閱讀.

IP: 104.238.184.237

Port: 8080

您也可以選擇下載 JAR 文件到本地,運行在您的本地進(jìn)行調(diào)試 Download JAR

下載后使用下面的代碼將其運行起來java -jar SocketServerDemo.jar

簡單的長連接

OkSocket 會默認(rèn)對每一個 Open 的新通道做緩存管理,僅在第一次調(diào)用 Open 方法時創(chuàng)建 ConnectionManager 管理器,之后調(diào)用者可以通過獲取到該ConnectionManager的引用,繼續(xù)調(diào)用相關(guān)方法

ConnectionManager 主要負(fù)責(zé)該地址的套接字連接斷開發(fā)送消息等操作.
//連接參數(shù)設(shè)置(IP,端口號),這也是一個連接的唯一標(biāo)識,不同連接,該參數(shù)中的兩個值至少有其一不一樣
ConnectionInfo info = new ConnectionInfo("104.238.184.237", 8080);
//調(diào)用OkSocket,開啟這次連接的通道,調(diào)用通道的連接方法進(jìn)行連接.
OkSocket.open(info).connect();

有回調(diào)的長連接

注冊該通道的監(jiān)聽器,每個 Connection 通道中的監(jiān)聽器互相隔離,因此如果一個項目連接了多個 Socket 連接需要在每個 Connection 注冊自己的連接監(jiān)聽器,連接監(jiān)聽器是該 OkSocket 與用戶交互的唯一途徑

//連接參數(shù)設(shè)置(IP,端口號),這也是一個連接的唯一標(biāo)識,不同連接,該參數(shù)中的兩個值至少有其一不一樣
ConnectionInfo info = new ConnectionInfo("104.238.184.237", 8080);
//調(diào)用OkSocket,開啟這次連接的通道,拿到通道Manager
IConnectionManager manager = OkSocket.open(info);
//注冊Socket行為監(jiān)聽器,SocketActionAdapter是回調(diào)的Simple類,其他回調(diào)方法請參閱類文檔
manager.registerReceiver(new SocketActionAdapter(){
  @Override
  public void onSocketConnectionSuccess(Context context, ConnectionInfo info, String action) {
   Toast.makeText(context, "連接成功", LENGTH_SHORT).show();
  }
});
//調(diào)用通道進(jìn)行連接
manager.connect();

可配置的長連接

獲得 OkSocketOptions 的行為屬于比較高級的 OkSocket 調(diào)用方法,每個 Connection 將會對應(yīng)一個 OkSocketOptions,如果第一次調(diào)用 Open 時未指定 OkSocketOptions,OkSocket將會使用默認(rèn)的配置對象,默認(rèn)配置請見文檔下方的高級調(diào)用說明

//連接參數(shù)設(shè)置(IP,端口號),這也是一個連接的唯一標(biāo)識,不同連接,該參數(shù)中的兩個值至少有其一不一樣
ConnectionInfo info = new ConnectionInfo("104.238.184.237", 8080);
//調(diào)用OkSocket,開啟這次連接的通道,拿到通道Manager
IConnectionManager manager = OkSocket.open(info);
//獲得當(dāng)前連接通道的參配對象
OkSocketOptions options= manager.getOption();
//基于當(dāng)前參配對象構(gòu)建一個參配建造者類
OkSocketOptions.Builder builder = new OkSocketOptions.Builder(options);
//修改參配設(shè)置(其他參配請參閱類文檔)
builder.setSinglePackageBytes(size);
//建造一個新的參配對象并且付給通道
manager.option(builder.build());
//調(diào)用通道進(jìn)行連接
manager.connect();

如何進(jìn)行數(shù)據(jù)發(fā)送

//類A:
//...定義將要發(fā)送的數(shù)據(jù)結(jié)構(gòu)體...
public class TestSendData implements ISendable {
  private String str = "";

  public TestSendData() {
    JSONObject jsonObject = new JSONObject();
    try {
      jsonObject.put("cmd", 14);
      jsonObject.put("data", "{x:2,y:1}");
      str = jsonObject.toString();
    } catch (JSONException e) {
      e.printStackTrace();
    }
  }

  @Override
  public byte[] parse() {
    //根據(jù)服務(wù)器的解析規(guī)則,構(gòu)建byte數(shù)組
    byte[] body = str.getBytes(Charset.defaultCharset());
    ByteBuffer bb = ByteBuffer.allocate(4 + body.length);
    bb.order(ByteOrder.BIG_ENDIAN);
    bb.putInt(body.length);
    bb.put(body);
    return bb.array();
  }
}

//類B:
private IConnectionManager mManager;
//...省略連接及設(shè)置回調(diào)的代碼...
@Override
public void onSocketConnectionSuccess(Context context, ConnectionInfo info, String action) {
   //連接成功其他操作...
   //鏈?zhǔn)骄幊陶{(diào)用
   OkSocket.open(info)
    .send(new TestSendData());
   
   //此處也可將ConnectManager保存成成員變量使用.
   mManager = OkSocket.open(info);
   if(mManager != null){
    mManager.send(new TestSendData());
   }
   //以上兩種方法選擇其一,成員變量的方式請注意判空
}

如何接收數(shù)據(jù)

OkSocket客戶端接收服務(wù)器數(shù)據(jù)是要求一定格式的,客戶端的OkSocketOptions提供了接口來修改默認(rèn)的服務(wù)器返回的包頭解析規(guī)則.請看下圖為默認(rèn)的包頭包體解析規(guī)則

 OkSocket與Android怎么用

數(shù)據(jù)結(jié)構(gòu)示意圖

如上圖包頭中的內(nèi)容為4個字節(jié)長度的int型,該int值標(biāo)識了包體數(shù)據(jù)區(qū)的長度,這就是默認(rèn)的頭解析,如果需要自定義頭請按照如下方法.

//設(shè)置自定義解析頭
OkSocketOptions.Builder okOptionsBuilder = new OkSocketOptions.Builder(mOkOptions);
okOptionsBuilder.setHeaderProtocol(new IHeaderProtocol() {
  @Override
  public int getHeaderLength() {
    //返回自定義的包頭長度,框架會解析該長度的包頭
    return 0;
  }

  @Override
  public int getBodyLength(byte[] header, ByteOrder byteOrder) {
    //從header(包頭數(shù)據(jù))中解析出包體的長度,byteOrder是你在參配中配置的字節(jié)序,可以使用ByteBuffer比較方便解析
    return 0;
  }
});
//將新的修改后的參配設(shè)置給連接管理器
mManager.option(okOptionsBuilder.build());


//...正確設(shè)置解析頭之后...
@Override
public void onSocketReadResponse(Context context, ConnectionInfo info, String action, OriginalData data) {
  //遵循以上規(guī)則,這個回調(diào)才可以正常收到服務(wù)器返回的數(shù)據(jù),數(shù)據(jù)在OriginalData中,為byte[]數(shù)組,該數(shù)組數(shù)據(jù)已經(jīng)處理過字節(jié)序問題,直接放入ByteBuffer中即可使用
}

如何保持心跳

//類A:
//...定義心跳管理器需要的心跳數(shù)據(jù)類型...
public class PulseData implements IPulseSendable {
  private String str = "pulse";

  @Override
  public byte[] parse() {
    byte[] body = str.getBytes(Charset.defaultCharset());
    ByteBuffer bb = ByteBuffer.allocate(4 + body.length);
    bb.order(ByteOrder.BIG_ENDIAN);
    bb.putInt(body.length);
    bb.put(body);
    return bb.array();
  }
}

//類B:
private IConnectionManager mManager;
private PulseData mPulseData = new PulseData;
//...省略連接及設(shè)置回調(diào)的代碼...
@Override
public void onSocketConnectionSuccess(Context context, ConnectionInfo info, String action) {
   //連接成功其他操作...
   //鏈?zhǔn)骄幊陶{(diào)用,給心跳管理器設(shè)置心跳數(shù)據(jù),一個連接只有一個心跳管理器,因此數(shù)據(jù)只用設(shè)置一次,如果斷開請再次設(shè)置.
   OkSocket.open(info)
    .getPulseManager()
    .setPulseSendable(mPulseData)
    .pulse();//開始心跳,開始心跳后,心跳管理器會自動進(jìn)行心跳觸發(fā)
        
   //此處也可將ConnectManager保存成成員變量使用.
   mManager = OkSocket.open(info);
   if(mManager != null){
    PulseManager pulseManager = mManager.getPulseManager();
    //給心跳管理器設(shè)置心跳數(shù)據(jù),一個連接只有一個心跳管理器,因此數(shù)據(jù)只用設(shè)置一次,如果斷開請再次設(shè)置.
    pulseManager.setPulseSendable(mPulseData);
    //開始心跳,開始心跳后,心跳管理器會自動進(jìn)行心跳觸發(fā)
    pulseManager.pulse();
   }
   //以上兩種方法選擇其一,成員變量的方式請注意判空
}

心跳接收到了之后需要進(jìn)行喂狗

因為我們的客戶端需要知道服務(wù)器收到了此次心跳,因此服務(wù)器在收到心跳后需要進(jìn)行應(yīng)答,我們收到此次心跳應(yīng)答后,需要進(jìn)行本地的喂狗操作,否則當(dāng)超過一定次數(shù)的心跳發(fā)送,未得到喂狗操作后,狗將會將此次連接斷開重連.

//定義成員變量
private IConnectionManager mManager;
//當(dāng)客戶端收到消息后
@Override
public void onSocketReadResponse(Context context, ConnectionInfo info, String action, OriginalData data) {
  if(mManager != null && 是心跳返回包){//是否是心跳返回包,需要解析服務(wù)器返回的數(shù)據(jù)才可知道
    //喂狗操作
    mManager.getPulseManager().feed();
  }
}

如何手動觸發(fā)一次心跳,在任何時間

//定義成員變量
private IConnectionManager mManager;
//...在任意地方...
mManager = OkSocket.open(info);
if(mManager != null){
  PulseManager pulseManager = mManager.getPulseManager();
  //手動觸發(fā)一次心跳(主要用于一些需要手動控制觸發(fā)時機的場景)
  pulseManager.trigger();
}

OkSocket參配選項及回調(diào)說明

OkSocketOptions

  1. Socket通訊模式mIOThreadMode

  2. 連接是否管理保存isConnectionHolden

  3. 寫入字節(jié)序mWriteOrder

  4. 讀取字節(jié)序mReadByteOrder

  5. 頭字節(jié)協(xié)議mHeaderProtocol

  6. 發(fā)送單個數(shù)據(jù)包的總長度mSendSinglePackageBytes

  7. 單次讀取的緩存字節(jié)長度mReadSingleTimeBufferBytes

  8. 脈搏頻率間隔毫秒數(shù)mPulseFrequency

  9. 脈搏最大丟失次數(shù)(狗的失喂次數(shù))mPulseFeedLoseTimes

  10. 后臺存活時間(分鐘)mBackgroundLiveMinute

  11. 連接超時時間(秒)mConnectTimeoutSecond

  12. 最大讀取數(shù)據(jù)的兆數(shù)(MB)mMaxReadDataMB

  13. 重新連接管理器mReconnectionManager

ISocketActionListener

  1. Socket讀寫線程啟動后回調(diào)onSocketIOThreadStart

  2. Socket讀寫線程關(guān)閉后回調(diào)onSocketIOThreadShutdown

  3. Socket連接狀態(tài)由連接->斷開回調(diào)onSocketDisconnection

  4. Socket連接成功回調(diào)onSocketConnectionSuccess

  5. Socket連接失敗回調(diào)onSocketConnectionFailed

  6. Socket從服務(wù)器讀取到字節(jié)回調(diào)onSocketReadResponse

  7. Socket寫給服務(wù)器字節(jié)后回調(diào)onSocketWriteResponse

  8. 發(fā)送心跳后的回調(diào)onPulseSend

Copyright [2017] [徐昊]

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

感謝各位的閱讀!關(guān)于“OkSocket與Android怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI