#android #kotlin #websocket #em-websocket-client
#Android #kotlin #websocket #em-websocket-client
Вопрос:
Я хочу, чтобы сокет был открыт, пока мое приложение находится на переднем плане. Я использую JAVA Api WebSocketClient отсюда:
Итак, я создал менеджер, который реализует интерфейс WebSocketClient с обратными вызовами onOpen, OnClose, onMessage и onError следующим образом. У меня также есть таймер PingPong, поэтому я могу проверять свое соединение каждые 10 секунд. интервал. Цикл этого процесса связан с жизненным циклом приложения, поэтому, когда приложение выходит на передний план, я вызываю connect and startPingPongTimer
методы, а когда оно переходит на задний kill and stopPingPongTimer
план, методы. URL-адрес WSS — это веб-сокет от Amazon Web Services. Моя проблема в том, что иногда я вызываю метод connect и никогда не получаю обратный вызов onOpen. Я также иногда получаю обратный вызов OnClose после отключения и повторного подключения, поэтому я не могу обработать текущее соединение, поскольку получаю OnClose от предыдущего.
class FlowSocketManagerImpl: FlowSocketManager {
private var isFlowing: Boolean = false
private val scope = CoroutineScope(Dispatchers.IO SupervisorJob())
private var pingPongTimer = object: CountDownTimer(10000, 1000) {
override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() {
println("On Finish")
send("Hello")
this.start()
}
}
private val mWebSocketClient = object : WebSocketClient(URI(Wss)) {
override fun onOpen(serverHandshake: ServerHandshake?) {
println("onOpen")
isFlowing = true
}
override fun onMessage(envelope: String?) {
println("onMessage $envelope")
}
override fun onClose(code: Int, reason: String, remote: Boolean) {
println("onClose $code $reason $remote")
isFlowing = false
socketBackOffStrategy(code)
}
override fun onError(e: Exception) {
e.printStackTrace()
println("onError ${e.message}")
isFlowing = false
}
}
@Throws(Exception::class)
override fun connect() {
mWebSocketClient.close()
mWebSocketClient.connectionLostTimeout = 10
if (mWebSocketClient.isClosed)
mWebSocketClient.connect()
}
override fun send(envelope: String) {
try {
mWebSocketClient.send(envelope)
} catch (e: WebsocketNotConnectedException) {
// ToDo Mark as unread
println("No connection")
}
}
override fun kill() {
if (mWebSocketClient.isOpen) {
mWebSocketClient.close()
}
}
private fun socketBackOffStrategy(code: Int) {
when (code) {
-1 -> {
// NetWork Unavailable
scope.launch {
delay(10000)
withContext(Dispatchers.Main) {
connect()
}
}
}
1000 -> {
// Successfully disconnected
}
1006 -> {
// 1006 The connection was closed because the other endpoint did not respond with a pong in time.
// For more information check: https://github.com/TooTallNate/Java-WebSocket/wiki/Lost-connection-detection
if (mWebSocketClient.isClosed)
connect()
}
}
}
override fun startPingPongCountDown() {
pingPongTimer.start()
}
override fun stopPingPongCountDown() {
pingPongTimer.cancel()
}
}
Какой наилучший способ или библиотеку использовать для моих целей или как я могу сделать его более надежным, эффективным и стабильным?
Спасибо
Ответ №1:
После долгих поисков я нашел библиотеку, которая выполняет всю эту работу самостоятельно. Он называется Scarlet и разработан Tinder. https://github.com/Tinder/Scarlet