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
Register Listener
Register a MediaEventsListener to receive media event callbacks:
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...
})
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...
});
The listener is automatically removed when the LifecycleOwner (Activity/Fragment) is destroyed, preventing memory leaks.
Callbacks
onAudioMuted
Triggered when your local audio is muted.
override fun onAudioMuted() {
Log.d(TAG, "Audio muted")
// Update mute button UI state
updateMuteButtonState(isMuted = true)
}
@Override
public void onAudioMuted() {
Log.d(TAG, "Audio muted");
// Update mute button UI state
updateMuteButtonState(true);
}
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.
override fun onAudioUnMuted() {
Log.d(TAG, "Audio unmuted")
// Update mute button UI state
updateMuteButtonState(isMuted = false)
}
@Override
public void onAudioUnMuted() {
Log.d(TAG, "Audio unmuted");
// Update mute button UI state
updateMuteButtonState(false);
}
Use Cases:
- Update mute button icon/state
- Hide muted indicator
- Sync UI with actual audio state
onVideoPaused
Triggered when your local video is paused.
override fun onVideoPaused() {
Log.d(TAG, "Video paused")
// Update video button UI state
updateVideoButtonState(isPaused = true)
// Show avatar instead of video preview
}
@Override
public void onVideoPaused() {
Log.d(TAG, "Video paused");
// Update video button UI state
updateVideoButtonState(true);
// Show avatar instead of video preview
}
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.
override fun onVideoResumed() {
Log.d(TAG, "Video resumed")
// Update video button UI state
updateVideoButtonState(isPaused = false)
// Show video preview
}
@Override
public void onVideoResumed() {
Log.d(TAG, "Video resumed");
// Update video button UI state
updateVideoButtonState(false);
// Show video preview
}
Use Cases:
- Update video toggle button state
- Show local video preview
- Sync UI with actual video state
onRecordingStarted
Triggered when session recording starts.
override fun onRecordingStarted() {
Log.d(TAG, "Recording started")
// Show recording indicator
showRecordingIndicator(true)
// Notify user that recording is active
}
@Override
public void onRecordingStarted() {
Log.d(TAG, "Recording started");
// Show recording indicator
showRecordingIndicator(true);
// Notify user that recording is active
}
Use Cases:
- Display recording indicator (red dot)
- Update recording button state
- Show notification to participants
onRecordingStopped
Triggered when session recording stops.
override fun onRecordingStopped() {
Log.d(TAG, "Recording stopped")
// Hide recording indicator
showRecordingIndicator(false)
}
@Override
public void onRecordingStopped() {
Log.d(TAG, "Recording stopped");
// Hide recording indicator
showRecordingIndicator(false);
}
Use Cases:
- Hide recording indicator
- Update recording button state
- Show recording saved notification
onScreenShareStarted
Triggered when you start sharing your screen.
override fun onScreenShareStarted() {
Log.d(TAG, "Screen sharing started")
// Update screen share button state
updateScreenShareButtonState(isSharing = true)
// Show screen share preview
}
@Override
public void onScreenShareStarted() {
Log.d(TAG, "Screen sharing started");
// Update screen share button state
updateScreenShareButtonState(true);
// Show screen share preview
}
Use Cases:
- Update screen share button state
- Show “You are sharing” indicator
- Minimize local video preview
onScreenShareStopped
Triggered when you stop sharing your screen.
override fun onScreenShareStopped() {
Log.d(TAG, "Screen sharing stopped")
// Update screen share button state
updateScreenShareButtonState(isSharing = false)
// Restore normal view
}
@Override
public void onScreenShareStopped() {
Log.d(TAG, "Screen sharing stopped");
// Update screen share button state
updateScreenShareButtonState(false);
// Restore normal view
}
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).
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)
}
}
@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;
}
}
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).
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)
}
}
@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;
}
}
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:
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"
}
}
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));
}
});
}
}
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