Держите соединение с сокетами открытым на жизненном цикле приложения Android

#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