Listen for State Changes and Events

You can add listeners for state changes and events during a chat session and respond accordingly. For instance, when the client ends a session, you can display a dialog to the user.
Important

Important

The legacy chat product is scheduled for retirement on February 14, 2026, and is in maintenance mode until then. During this phase, you can continue to use chat, but we no longer recommend that you implement new chat channels. To avoid service interruptions to your customers, migrate to Messaging for In-App and Web before that date. Messaging offers many of the chat features that you love plus asynchronous conversations that can be picked back up at any time. Learn about chat retirement in Help.

  1. Create a SessionStateListener implementation to handle session state changes.

    In Java:

    public class MySessionStateListener implements SessionStateListener {
    
      @Override public void onSessionStateChange (ChatSessionState state) {
        if (state == ChatSessionState.Disconnected) {
          // TODO: Handle the disconnected state change
        }
      }
    
      @Override public void onSessionEnded (ChatEndReason endReason) {
        if (endReason == ChatEndReason.EndedByAgent) {
          // TODO: Show a UI telling the user that the agent ended the session
        }
      }
    }

    In Kotlin:

    class MySessionStateListener: SessionStateListener {
    
      override fun onSessionStateChange(state: ChatSessionState?) {
        if (state == ChatSessionState.Disconnected) {
          // TODO: Handle the disconnected state change
        }
      }
    
      override fun onSessionEnded(endReason: ChatEndReason?) {
        if (endReason == ChatEndReason.EndedByAgent) {
          // TODO: Show a UI telling the user that the agent ended the session
        }
      }
    }

    This implementation handles state changes (onSessionStateChange) and why the session ended (onSessionEnded). For information on other session states and reasons for ending, see ChatSessionState and ChatEndReason.

  2. Create a ChatEventListener implementation if you want to listen for additional events.

    This listener isn’t required, but it can be used to listen for events such as: when an agent joins (agentJoined), when a message is sent (processedOutgoingMessage), when a message is received (didReceiveMessage).

    In Java:

    public class MyEventListener implements ChatEventListener {
        public void agentJoined (AgentInformation agentInformation) {
            // Handle agent joined
        }
    
        public void processedOutgoingMessage (String message) {
            // Handle outgoing message processed
        }
    
        public void didSelectMenuItem (ChatWindowMenu.MenuItem menuItem) {
            // Handle chatbot menu selected
        }
    
        public void didSelectButtonItem (ChatWindowButtonMenu.Button buttonItem) {
            // Handle chatbot button selected
        }
    
        public void didSelectFooterMenuItem (ChatFooterMenu.MenuItem footerMenuItem) {
            // Handle chatboot footer menu selected
        }
    
        public void didReceiveMessage (ChatMessage chatMessage) {
            // Handle received message
        }
    
        public void transferToButtonInitiated () {
            // Handle transfer to agent
        }
    
        public void agentIsTyping (boolean isUserTyping) {
            // Handle typing update
        }
    }

    In Kotlin:

    class MyEventListener : ChatEventListener {
        override fun agentJoined(agentInformation: AgentInformation) {
            // Handle agent joined
        }
    
        override fun processedOutgoingMessage(message: String) {
            // Handle outgoing message processed
        }
    
        override fun didSelectMenuItem(menuItem: ChatWindowMenu.MenuItem) {
            // Handle chatbot menu selected
        }
    
        override fun didSelectButtonItem(buttonItem: ChatWindowButtonMenu.Button) {
            // Handle chatbot button selected
        }
    
        override fun didSelectFooterMenuItem(footerMenuItem: ChatFooterMenu.MenuItem) {
            // Handle chatboot footer menu selected
        }
    
        override fun didReceiveMessage(chatMessage: ChatMessage) {
            // Handle received message
        }
    
        override fun transferToButtonInitiated() {
            // Handle transfer to agent
        }
    
        override fun agentIsTyping(isUserTyping: Boolean) {
            // Handle typing update
        }
    }
  3. Create a SessionInfoListener implementation if you want to get session information.

    In Java:

    public class MySessionInfoListener implements SessionInfoListener {
    
        public void onSessionInfoReceived (ChatSessionInfo chatSessionInfo) {
            // TO DO: Do something with the session ID
            String sessionId = chatSessionInfo.getSessionId();
    }

    In Kotlin:

    class MySessionInfoListener : SessionInfoListener {
    
        override fun onSessionInfoReceived(chatSessionInfo: ChatSessionInfo) {
            // TO DO: Do something with the session ID
            val sessionId = chatSessionInfo.getSessionId()
        }
    }
  4. Instantiate your listener instances from your Application class.

    In Java:

    private MySessionStateListener mSessionStateListener;
    private MyEventListener mEventListener;
    private MySessionInfoListener mSessionInfoListener;
    
    @Override public void onCreate () {
      super.onCreate();
      mSessionStateListener = new MySessionStateListener();
      mEventListener = new MyEventListener();
      mSessionInfoListener = new MySessionInfoListener();
    }
    
    public SessionStateListener getSessionStateListener () {
      return mSessionStateListener;
    }
    
    public ChatEventListener getEventListener () {
      return mEventListener;
    }
    
    public SessionInfoListener getSessionInfoListener () {
      return mSessionInfoListener;
    }

    In Kotlin:

    val mSessionStateListener = MySessionStateListener()
    val mEventListener = MyEventListener()
    val mSessionInfoListener = MySessionInfoListener()
    Note

    Note

    It’s important to have the listener at the Application scope to ensure that the session is trackable throughout the lifetime of the application rather than just within an Activity.

  5. When you configure and start a session, add the listeners that you implemented. Add the event listener (ChatEventListener) to the chat UI configuration object. Add the session info listener (SessionInfoListener) and the session state listener (SessionStateListener) to the chat UI client.

    In Java:

    // Create a UI configuration instance from a core instance 
    // and add our event listener
    ChatUIConfiguration.Builder uiConfig = new ChatUIConfiguration.Builder()
      .chatConfiguration(chatConfiguration)
      .chatEventListener((MyApplication)getApplication()).getEventListener());
    
    // Create a chat session and add our session listener
    ChatUI.configure(uiConfig.build())
      .createClient(getApplicationContext())
      .onResult(new Async.ResultHandler<ChatUIClient>() {
          @Override public void handleResult (Async<?> operation, 
            ChatUIClient chatUIClient) {
    
                SessionStateListener sessionStateListener =
                    ((MyApplication)getApplication()).getSessionStateListener();
                chatUIClient.addSessionStateListener(sessionStateListener);
    
                SessionInfoListener sessionInfoListener =
                    ((MyApplication)getApplication()).getSessionInfoListener();
                chatUIClient.addSessionInfoListener(sessionInfoListener);
    
                chatUIClient.startChatSession(MainActivity.this);
            }
    });

    In Kotlin:

    // Create a UI configuration instance from a core instance
    // and add our event listener
    val uiConfig = ChatUIConfiguration.Builder()
        .chatConfiguration(chatConfiguration)
        .chatEventListener(mEventListener)
    
    // Create a chat session and add our session listener
    ChatUI.configure(uiConfig.build())
        .createClient(applicationContext)
        .onResult { operation, chatUIClient ->
            chatUIClient.addSessionStateListener(mSessionStateListener)
            chatUIClient.addSessionInfoListener(mSessionInfoListener)
            chatUIClient.startChatSession(this@MainActivity)
        }