Amazon IVS Chat Client Messaging - Android - Execute connect method in onResume won't bring the connection back after disconnect execution in onPause

0

I'm building an Android app with chat functionalities using Amazon IVS Chat Client Messaging SDK and I stucked with handling lifecycle of the chat room and web socket connection.

According to the documentation Disconnect from a Chat Room:

Because the WebSocket connection will stop working after a short time when the application is in a background state, we recommend that you manually connect/disconnect when transitioning from/to a background state. To do so, match the room.connect() call in the onResume() lifecycle method, on Android Activity or Fragment, with a room.disconnect() call in the onPause() lifecycle method.

So I implemented that way, but I never get connected state back again (I need to close activity and open it again, then all works fine):

🟢 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTING) Changed state: DISCONNECTED -> CONNECTING
🟤 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTING) Calling onConnecting
🟤 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTING) Requesting token
🟤 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTING) Did receive token: ChatToken(token=CHAT_TOKEN_HERE#1, sessionExpirationTime=Fri Sep 08 13:20:24 GMT+02:00 2023, tokenExpirationTime=Fri Sep 08 13:20:24 GMT+02:00 2023)
🟤 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTING) Connecting to web socket wss://edge.ivschat.us-east-1.amazonaws.com
🟢 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTED) Changed state: CONNECTING -> CONNECTED
🟤 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTED) Calling onConnected
🟢 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTED) Connected
// App moves to ON_PAUSE state
🟢 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (DISCONNECTED) Changed state: CONNECTED -> DISCONNECTED
🟤 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (DISCONNECTED) Calling onDisconnected
🟢 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (DISCONNECTED) Did receive socket onClosing event: disconnect reason CLIENT_DISCONNECT, socket code 1000, socket reason: 
🟢 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (DISCONNECTED) Reconnect not needed: disconnect reason CLIENT_DISCONNECT
// APP moves to ON_RESUME state
🟢 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTING) Changed state: DISCONNECTED -> CONNECTING
🟤 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTING) Calling onConnecting
🟤 Room 58a2b001-7c9c-4c2b-935b-ef07e74cc2c3 (CONNECTING) Requesting token

I keep seeing Requesting token. For the demo app I found here, I noticed that you didn't execute disconnect method explicitly when app lifecycle changes state to Pause/Stop. Was it implemented on purpose?

Please take a look on implementation of wrapper for ChatRoom class. Did I miss something?.:

internal class ChatRemoteApiImpl @Inject constructor(
    private val webinarRemoteApi: WebinarRemoteApi,
    private val chatClientStateMapper: ChatClientStateMapper,
    private val chatMessageRemoteMapper: ChatMessageRemoteMapper,
) : ChatRemoteApi {

    private var _chatRoom: ChatRoom? = null
        set(value) {
            field = value
            if (value != null) {
                mutableChatRoomFlow.tryEmit(value)
            }
        }

    private val isConnected: Boolean
        get() {
            return chatRoom.state == ChatRoom.State.CONNECTED
        }

    private val mutableChatRoomFlow = bufferedFlow<ChatRoom>(replay = 1)

    private val chatRoom: ChatRoom
        get() {
            return checkNotNull(_chatRoom) { "Chat Room need to be initialized" }
        }

    override val stateChange: Flow<State>
        get() = mutableChatRoomFlow.take(1)
            .flatMapLatest { chatRoom ->
                chatRoom.stateChanges()
                    .map(chatClientStateMapper::map)
            }

    override val messages: Flow<ChatMessageResponse>
        get() = mutableChatRoomFlow.take(1)
            .flatMapLatest { chatRoom ->
                chatRoom.receivedMessages()
                    .map(chatMessageRemoteMapper::map)
            }

    override suspend fun createClient(params: ChatClientParams) {
        val chatTokenProvider: suspend () -> ChatToken = suspend {
            val response = webinarRemoteApi.createChatToken(params.webinarId, params.userId)
            with(response) {
                ChatToken(
                    token,
                    tokenExpirationTime.toDate(),
                    sessionExpirationTime.toDate(),
                )
            }
        }

        _chatRoom = ChatRoom(
            regionOrUrl = params.region,
            tokenProvider = chatTokenProvider,
        )
    }

    override fun connect() {       // call onResume
        if (!isConnected) {
            chatRoom.connect()
        }
    }

    override fun disconnect() {   // call onPause
        chatRoom.disconnect()
    }
}

I see two solutions:

  1. Never call disconnect, just keep the connection no matter of lifecycle. (Only disconnect before killing the activity). - But from the documentation I see that if app stays in background for long time then the socket connection stops. So that solution may not work well.
  2. Second options is to re-create new chat room every time the app comes back from background.
asked 8 months ago78 views
No Answers

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions