> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-v6-beta2-flutter-uikit.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Media Events Listener

Monitor local media state changes with `MediaEventsListener`. This listener provides callbacks for your own audio/video state changes, recording events, screen sharing, audio mode changes, and camera facing changes.

## Prerequisites

* An active [call session](/calls/android/join-session)
* Access to the `CallSession` instance

## Register Listener

Register a `MediaEventsListener` to receive media event callbacks:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    val callSession = CallSession.getInstance()

    callSession.addMediaEventsListener(this, object : MediaEventsListener() {
        override fun onAudioMuted() {
            Log.d(TAG, "Audio muted")
        }

        override fun onAudioUnMuted() {
            Log.d(TAG, "Audio unmuted")
        }

        override fun onVideoPaused() {
            Log.d(TAG, "Video paused")
        }

        override fun onVideoResumed() {
            Log.d(TAG, "Video resumed")
        }

        // Additional callbacks...
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    CallSession callSession = CallSession.getInstance();

    callSession.addMediaEventsListener(this, new MediaEventsListener() {
        @Override
        public void onAudioMuted() {
            Log.d(TAG, "Audio muted");
        }

        @Override
        public void onAudioUnMuted() {
            Log.d(TAG, "Audio unmuted");
        }

        @Override
        public void onVideoPaused() {
            Log.d(TAG, "Video paused");
        }

        @Override
        public void onVideoResumed() {
            Log.d(TAG, "Video resumed");
        }

        // Additional callbacks...
    });
    ```
  </Tab>
</Tabs>

<Note>
  The listener is automatically removed when the `LifecycleOwner` (Activity/Fragment) is destroyed, preventing memory leaks.
</Note>

***

## Callbacks

### onAudioMuted

Triggered when your local audio is muted.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onAudioMuted() {
        Log.d(TAG, "Audio muted")
        // Update mute button UI state
        updateMuteButtonState(isMuted = true)
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onAudioMuted() {
        Log.d(TAG, "Audio muted");
        // Update mute button UI state
        updateMuteButtonState(true);
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Update mute button icon/state
* Show muted indicator in UI
* Sync UI with actual audio state

***

### onAudioUnMuted

Triggered when your local audio is unmuted.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onAudioUnMuted() {
        Log.d(TAG, "Audio unmuted")
        // Update mute button UI state
        updateMuteButtonState(isMuted = false)
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onAudioUnMuted() {
        Log.d(TAG, "Audio unmuted");
        // Update mute button UI state
        updateMuteButtonState(false);
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Update mute button icon/state
* Hide muted indicator
* Sync UI with actual audio state

***

### onVideoPaused

Triggered when your local video is paused.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onVideoPaused() {
        Log.d(TAG, "Video paused")
        // Update video button UI state
        updateVideoButtonState(isPaused = true)
        // Show avatar instead of video preview
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onVideoPaused() {
        Log.d(TAG, "Video paused");
        // Update video button UI state
        updateVideoButtonState(true);
        // Show avatar instead of video preview
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Update video toggle button state
* Show avatar/placeholder in local preview
* Sync UI with actual video state

***

### onVideoResumed

Triggered when your local video is resumed.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onVideoResumed() {
        Log.d(TAG, "Video resumed")
        // Update video button UI state
        updateVideoButtonState(isPaused = false)
        // Show video preview
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onVideoResumed() {
        Log.d(TAG, "Video resumed");
        // Update video button UI state
        updateVideoButtonState(false);
        // Show video preview
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Update video toggle button state
* Show local video preview
* Sync UI with actual video state

***

### onRecordingStarted

Triggered when session recording starts.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onRecordingStarted() {
        Log.d(TAG, "Recording started")
        // Show recording indicator
        showRecordingIndicator(true)
        // Notify user that recording is active
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onRecordingStarted() {
        Log.d(TAG, "Recording started");
        // Show recording indicator
        showRecordingIndicator(true);
        // Notify user that recording is active
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Display recording indicator (red dot)
* Update recording button state
* Show notification to participants

***

### onRecordingStopped

Triggered when session recording stops.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onRecordingStopped() {
        Log.d(TAG, "Recording stopped")
        // Hide recording indicator
        showRecordingIndicator(false)
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onRecordingStopped() {
        Log.d(TAG, "Recording stopped");
        // Hide recording indicator
        showRecordingIndicator(false);
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Hide recording indicator
* Update recording button state
* Show recording saved notification

***

### onScreenShareStarted

Triggered when you start sharing your screen.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onScreenShareStarted() {
        Log.d(TAG, "Screen sharing started")
        // Update screen share button state
        updateScreenShareButtonState(isSharing = true)
        // Show screen share preview
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onScreenShareStarted() {
        Log.d(TAG, "Screen sharing started");
        // Update screen share button state
        updateScreenShareButtonState(true);
        // Show screen share preview
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Update screen share button state
* Show "You are sharing" indicator
* Minimize local video preview

***

### onScreenShareStopped

Triggered when you stop sharing your screen.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onScreenShareStopped() {
        Log.d(TAG, "Screen sharing stopped")
        // Update screen share button state
        updateScreenShareButtonState(isSharing = false)
        // Restore normal view
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onScreenShareStopped() {
        Log.d(TAG, "Screen sharing stopped");
        // Update screen share button state
        updateScreenShareButtonState(false);
        // Restore normal view
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Update screen share button state
* Hide "You are sharing" indicator
* Restore local video preview

***

### onAudioModeChanged

Triggered when the audio output mode changes (speaker, earpiece, bluetooth).

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onAudioModeChanged(audioMode: AudioMode) {
        Log.d(TAG, "Audio mode changed to: $audioMode")
        // Update audio mode button/icon
        when (audioMode) {
            AudioMode.SPEAKER -> updateAudioModeIcon(R.drawable.ic_speaker)
            AudioMode.EARPIECE -> updateAudioModeIcon(R.drawable.ic_earpiece)
            AudioMode.BLUETOOTH -> updateAudioModeIcon(R.drawable.ic_bluetooth)
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onAudioModeChanged(AudioMode audioMode) {
        Log.d(TAG, "Audio mode changed to: " + audioMode);
        // Update audio mode button/icon
        switch (audioMode) {
            case SPEAKER:
                updateAudioModeIcon(R.drawable.ic_speaker);
                break;
            case EARPIECE:
                updateAudioModeIcon(R.drawable.ic_earpiece);
                break;
            case BLUETOOTH:
                updateAudioModeIcon(R.drawable.ic_bluetooth);
                break;
        }
    }
    ```
  </Tab>
</Tabs>

**AudioMode Values:**

| Value       | Description                                     |
| ----------- | ----------------------------------------------- |
| `SPEAKER`   | Audio output through device speaker             |
| `EARPIECE`  | Audio output through earpiece                   |
| `BLUETOOTH` | Audio output through connected Bluetooth device |

**Use Cases:**

* Update audio mode button icon
* Show current audio output device
* Handle Bluetooth connection/disconnection

***

### onCameraFacingChanged

Triggered when the camera facing changes (front/back).

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onCameraFacingChanged(facing: CameraFacing) {
        Log.d(TAG, "Camera facing changed to: $facing")
        // Update camera switch button state
        when (facing) {
            CameraFacing.FRONT -> updateCameraIcon(R.drawable.ic_camera_front)
            CameraFacing.BACK -> updateCameraIcon(R.drawable.ic_camera_back)
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onCameraFacingChanged(CameraFacing facing) {
        Log.d(TAG, "Camera facing changed to: " + facing);
        // Update camera switch button state
        switch (facing) {
            case FRONT:
                updateCameraIcon(R.drawable.ic_camera_front);
                break;
            case BACK:
                updateCameraIcon(R.drawable.ic_camera_back);
                break;
        }
    }
    ```
  </Tab>
</Tabs>

**CameraFacing Values:**

| Value   | Description                         |
| ------- | ----------------------------------- |
| `FRONT` | Front-facing camera (selfie camera) |
| `BACK`  | Back-facing camera (main camera)    |

**Use Cases:**

* Update camera switch button icon
* Adjust UI for mirrored/non-mirrored preview
* Track camera state

***

## Complete Example

Here's a complete example handling all media events:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    class CallActivity : AppCompatActivity() {
        private lateinit var callSession: CallSession
        
        private lateinit var muteButton: ImageButton
        private lateinit var videoButton: ImageButton
        private lateinit var screenShareButton: ImageButton
        private lateinit var audioModeButton: ImageButton
        private lateinit var recordingIndicator: View

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_call)

            initViews()
            callSession = CallSession.getInstance()
            setupMediaEventsListener()
        }

        private fun initViews() {
            muteButton = findViewById(R.id.muteButton)
            videoButton = findViewById(R.id.videoButton)
            screenShareButton = findViewById(R.id.screenShareButton)
            audioModeButton = findViewById(R.id.audioModeButton)
            recordingIndicator = findViewById(R.id.recordingIndicator)
        }

        private fun setupMediaEventsListener() {
            callSession.addMediaEventsListener(this, object : MediaEventsListener() {
                override fun onAudioMuted() {
                    runOnUiThread {
                        muteButton.setImageResource(R.drawable.ic_mic_off)
                        muteButton.isSelected = true
                    }
                }

                override fun onAudioUnMuted() {
                    runOnUiThread {
                        muteButton.setImageResource(R.drawable.ic_mic_on)
                        muteButton.isSelected = false
                    }
                }

                override fun onVideoPaused() {
                    runOnUiThread {
                        videoButton.setImageResource(R.drawable.ic_videocam_off)
                        videoButton.isSelected = true
                    }
                }

                override fun onVideoResumed() {
                    runOnUiThread {
                        videoButton.setImageResource(R.drawable.ic_videocam_on)
                        videoButton.isSelected = false
                    }
                }

                override fun onRecordingStarted() {
                    runOnUiThread {
                        recordingIndicator.visibility = View.VISIBLE
                        Toast.makeText(
                            this@CallActivity,
                            "Recording started",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                }

                override fun onRecordingStopped() {
                    runOnUiThread {
                        recordingIndicator.visibility = View.GONE
                        Toast.makeText(
                            this@CallActivity,
                            "Recording stopped",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                }

                override fun onScreenShareStarted() {
                    runOnUiThread {
                        screenShareButton.isSelected = true
                        Toast.makeText(
                            this@CallActivity,
                            "You are sharing your screen",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                }

                override fun onScreenShareStopped() {
                    runOnUiThread {
                        screenShareButton.isSelected = false
                    }
                }

                override fun onAudioModeChanged(audioMode: AudioMode) {
                    runOnUiThread {
                        val iconRes = when (audioMode) {
                            AudioMode.SPEAKER -> R.drawable.ic_volume_up
                            AudioMode.EARPIECE -> R.drawable.ic_phone_in_talk
                            AudioMode.BLUETOOTH -> R.drawable.ic_bluetooth_audio
                        }
                        audioModeButton.setImageResource(iconRes)
                    }
                }

                override fun onCameraFacingChanged(facing: CameraFacing) {
                    runOnUiThread {
                        Log.d(TAG, "Camera switched to: $facing")
                    }
                }
            })
        }

        companion object {
            private const val TAG = "CallActivity"
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    public class CallActivity extends AppCompatActivity {
        private static final String TAG = "CallActivity";
        private CallSession callSession;
        
        private ImageButton muteButton;
        private ImageButton videoButton;
        private ImageButton screenShareButton;
        private ImageButton audioModeButton;
        private View recordingIndicator;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_call);

            initViews();
            callSession = CallSession.getInstance();
            setupMediaEventsListener();
        }

        private void initViews() {
            muteButton = findViewById(R.id.muteButton);
            videoButton = findViewById(R.id.videoButton);
            screenShareButton = findViewById(R.id.screenShareButton);
            audioModeButton = findViewById(R.id.audioModeButton);
            recordingIndicator = findViewById(R.id.recordingIndicator);
        }

        private void setupMediaEventsListener() {
            callSession.addMediaEventsListener(this, new MediaEventsListener() {
                @Override
                public void onAudioMuted() {
                    runOnUiThread(() -> {
                        muteButton.setImageResource(R.drawable.ic_mic_off);
                        muteButton.setSelected(true);
                    });
                }

                @Override
                public void onAudioUnMuted() {
                    runOnUiThread(() -> {
                        muteButton.setImageResource(R.drawable.ic_mic_on);
                        muteButton.setSelected(false);
                    });
                }

                @Override
                public void onVideoPaused() {
                    runOnUiThread(() -> {
                        videoButton.setImageResource(R.drawable.ic_videocam_off);
                        videoButton.setSelected(true);
                    });
                }

                @Override
                public void onVideoResumed() {
                    runOnUiThread(() -> {
                        videoButton.setImageResource(R.drawable.ic_videocam_on);
                        videoButton.setSelected(false);
                    });
                }

                @Override
                public void onRecordingStarted() {
                    runOnUiThread(() -> {
                        recordingIndicator.setVisibility(View.VISIBLE);
                        Toast.makeText(
                            CallActivity.this,
                            "Recording started",
                            Toast.LENGTH_SHORT
                        ).show();
                    });
                }

                @Override
                public void onRecordingStopped() {
                    runOnUiThread(() -> {
                        recordingIndicator.setVisibility(View.GONE);
                        Toast.makeText(
                            CallActivity.this,
                            "Recording stopped",
                            Toast.LENGTH_SHORT
                        ).show();
                    });
                }

                @Override
                public void onScreenShareStarted() {
                    runOnUiThread(() -> {
                        screenShareButton.setSelected(true);
                        Toast.makeText(
                            CallActivity.this,
                            "You are sharing your screen",
                            Toast.LENGTH_SHORT
                        ).show();
                    });
                }

                @Override
                public void onScreenShareStopped() {
                    runOnUiThread(() -> screenShareButton.setSelected(false));
                }

                @Override
                public void onAudioModeChanged(AudioMode audioMode) {
                    runOnUiThread(() -> {
                        int iconRes;
                        switch (audioMode) {
                            case SPEAKER:
                                iconRes = R.drawable.ic_volume_up;
                                break;
                            case EARPIECE:
                                iconRes = R.drawable.ic_phone_in_talk;
                                break;
                            case BLUETOOTH:
                                iconRes = R.drawable.ic_bluetooth_audio;
                                break;
                            default:
                                iconRes = R.drawable.ic_volume_up;
                        }
                        audioModeButton.setImageResource(iconRes);
                    });
                }

                @Override
                public void onCameraFacingChanged(CameraFacing facing) {
                    runOnUiThread(() -> Log.d(TAG, "Camera switched to: " + facing));
                }
            });
        }
    }
    ```
  </Tab>
</Tabs>

***

## Callbacks Summary

| Callback                | Parameter      | Description                  |
| ----------------------- | -------------- | ---------------------------- |
| `onAudioMuted`          | -              | Local audio was muted        |
| `onAudioUnMuted`        | -              | Local audio was unmuted      |
| `onVideoPaused`         | -              | Local video was paused       |
| `onVideoResumed`        | -              | Local video was resumed      |
| `onRecordingStarted`    | -              | Session recording started    |
| `onRecordingStopped`    | -              | Session recording stopped    |
| `onScreenShareStarted`  | -              | Local screen sharing started |
| `onScreenShareStopped`  | -              | Local screen sharing stopped |
| `onAudioModeChanged`    | `AudioMode`    | Audio output mode changed    |
| `onCameraFacingChanged` | `CameraFacing` | Camera facing changed        |

## Next Steps

<CardGroup cols={2}>
  <Card title="Button Click Listener" icon="hand-pointer" href="/calls/android/button-click-listener">
    Handle UI button click events
  </Card>

  <Card title="Audio Controls" icon="microphone" href="/calls/android/audio-controls">
    Control audio programmatically
  </Card>
</CardGroup>
