package com.xiaomakj.jetpackplug.utils
import android.annotation.SuppressLint
import android.content.Context
import android.util.Log
import com.google.gson.Gson
import com.xiaomakj.jetpackplug.App
import com.xiaomakj.jetpackplug.database.entity.BlazeMessage
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import okhttp3.*
import okio.ByteString
import java.util.concurrent.TimeUnit
class ChatWebSocket(
private val okHttpClient: OkHttpClient,
private val context: Context
) : WebSocketListener() {
private val failCode = 1000
private val quitCode = 1001
var connected: Boolean = false
private var client: WebSocket? = null
private val gson = Gson()
companion object {
const val WS_URL = "wss://xxx.xxx.xxx"
val TAG = ChatWebSocket::class.java.simpleName
}
init {
connected = false
}
@Synchronized
fun connect() {
if (client == null) {
connected = false
client = okHttpClient.newWebSocket(Request.Builder().url(WS_URL).build(), this)
}
}
@Synchronized
fun disconnect() {
if (client != null) {
closeInternal(quitCode)
connectTimer?.dispose()
client = null
connected = false
}
}
@Synchronized
fun sendMessage(blazeMessage: BlazeMessage): BlazeMessage? {
val bm: BlazeMessage? = null
if (client != null && connected) {
val result = client!!.send(gson.toJson(blazeMessage).gzip())
} else {
Log.e(TAG, "WebSocket not connect")
}
return bm
}
private fun sendPendingMessage() {
client?.send(gson.toJson(BlazeMessage("", "")).gzip())
}
@Synchronized
override fun onOpen(webSocket: WebSocket?, response: Response?) {
if (client != null) {
connected = true
client = webSocket
webSocketObserver?.onSocketOpen()
connectTimer?.dispose()
sendPendingMessage()
}
}
override fun onMessage(webSocket: WebSocket?, bytes: ByteString?) {
try {
val json = bytes?.ungzip()
val blazeMessage = gson.fromJson(json, BlazeMessage::class.java)
handleReceiveMessage(blazeMessage)
} catch (e: GzipException) {
}
}
@SuppressLint("CheckResult")
@Synchronized
override fun onClosed(webSocket: WebSocket?, code: Int, reason: String?) {
connected = false
if (code == failCode) {
closeInternal(code)
if (connectTimer == null || connectTimer?.isDisposed == true) connectTimer =
Observable.interval(2000, TimeUnit.MILLISECONDS).subscribe {
if (App.instance.networkConnected()) {
connect()
}
}
} else {
webSocket?.cancel()
}
}
private var connectTimer: Disposable? = null
@Synchronized
override fun onFailure(webSocket: WebSocket?, t: Throwable?, response: Response?) {
t?.let {
Log.e(TAG, "WebSocket onFailure ", it)
}
if (client != null) {
if (t != null) {
closeInternal(quitCode)
} else {
onClosed(webSocket, failCode, "OK")
}
}
}
private fun closeInternal(code: Int) {
try {
connected = false
if (client != null) {
client!!.close(code, "OK")
}
} catch (e: Exception) {
} finally {
client = null
webSocketObserver?.onSocketClose()
}
}
private fun handleReceiveMessage(blazeMessage: BlazeMessage) {
}
private fun makeMessageStatus(status: String, messageId: String) {
}
fun setWebSocketObserver(webSocketObserver: WebSocketObserver) {
this.webSocketObserver = webSocketObserver
}
private var webSocketObserver: WebSocketObserver? = null
interface WebSocketObserver {
fun onSocketClose()
fun onSocketOpen()
}
}
@Throws(IOException::class)
fun String.gzip(): ByteString {
val result = Buffer()
val sink = Okio.buffer(GzipSink(result))
sink.use {
sink.write(toByteArray())
}
return result.readByteString()
}
fun ByteString.ungzip(): String {
val buffer = Buffer().write(this)
val gzip = GzipSource(buffer as Source)
return Okio.buffer(gzip).readUtf8()
}
class GzipException : IOException()
fun Context.networkConnected(): Boolean {
val cm = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getSystemService(ConnectivityManager::class.java) ?: return false
} else {
return false
}
val network: NetworkInfo
try {
network = cm.activeNetworkInfo
} catch (t: Throwable) {
return false
}
return network != null && network.isConnected
}
Okhttp3 WebSocket簡單教程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.