import 'package:stream_video_flutter/stream_video_flutter.dart';
bool? _microphoneEnabledBeforeInterruption;
void _handleMobileAudioInterruptions() {
if (!CurrentPlatform.isMobile) return;
RtcMediaDeviceNotifier.instance.handleCallInterruptionCallbacks(
onInterruptionStart: () {
// Mute the microphone when interruption start
final call = StreamVideo.instance.activeCall;
_microphoneEnabledBeforeInterruption =
call?.state.value.localParticipant?.isAudioEnabled;
call?.setMicrophoneEnabled(enabled: false);
},
onInterruptionEnd: () {
// Unmute the microphone when interruption ends
if (_microphoneEnabledBeforeInterruption == true) {
StreamVideo.instance.activeCall?.setMicrophoneEnabled(enabled: true);
}
_microphoneEnabledBeforeInterruption = null;
},
androidInterruptionSource: AndroidInterruptionSource.audioFocusAndTelephony,
);
}
Handling System Audio Interruptions
Audio interruptions are a common occurrence on mobile devices that can disrupt ongoing video calls. The Stream Video Flutter SDK provides built-in support for handling these interruptions gracefully, allowing you to maintain a smooth user experience even when external audio events occur.
What are Audio Interruptions?
Audio interruptions happen when the system or other applications take over the audio session, temporarily pausing or stopping your app’s audio. Common examples include:
iOS Interruptions
- Incoming phone calls
- Siri activation
- Alarm or timer sounds
- Audio from other apps taking over (e.g., voice memo, navigation apps)
Android Interruptions
The interruption sources depend on the configured AndroidInterruptionSource
:
With Audio Focus:
- Other media apps interrupting (e.g., Spotify, YouTube)
- Assistant voice prompts (e.g., Google Assistant)
- Alarms and notifications
With Telephony:
- Phone calls (requires
READ_PHONE_STATE
permission)
Basic Implementation
The SDK provides the handleCallInterruptionCallbacks
method through RtcMediaDeviceNotifier
to manage audio interruptions.
In this example we disable the microphone during an interruption:
When multiple active calls are enabled, use StreamVideo.instance.activeCalls
instead.
Method Parameters
handleCallInterruptionCallbacks
Future<void> handleCallInterruptionCallbacks({
void Function()? onInterruptionStart,
void Function()? onInterruptionEnd,
AndroidInterruptionSource androidInterruptionSource =
AndroidInterruptionSource.audioFocusAndTelephony,
})
Parameters:
onInterruptionStart
: Callback function executed when an audio interruption startsonInterruptionEnd
: Callback function executed when an audio interruption endsandroidInterruptionSource
: Specifies which interruption sources to monitor on Android
On Android you can filter interruptions for audio and/or telephony, but on iOS you can only enable all interruptions.
Android Interruption Sources
enum AndroidInterruptionSource {
audioFocusOnly, // Monitor audio focus changes only
telephonyOnly, // Monitor phone calls only
audioFocusAndTelephony, // Monitor both (default)
}
Platform Setup
Android Permissions
To handle phone call interruptions on Android, add the following permissions to your android/app/src/main/AndroidManifest.xml
:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_CALL_STATE" />
Runtime Permission Request
Request the phone permission at runtime for Android:
void _requestPermissions() async {
if (CurrentPlatform.isAndroid) {
await Permission.phone.request();
}
}
Best Practices
1. Initialize Early
Set up interruption handling as early as possible in your app lifecycle:
@override
void initState() {
super.initState();
_handleMobileAudioInterruptions();
}
2. Platform Check
Always check if the platform is mobile before setting up interruption handling:
void _setupInterruptions() {
if (!CurrentPlatform.isMobile) return;
// Setup interruption handling
}
3. Graceful Degradation
Handle cases where permissions might not be granted:
void _setupWithPermissionCheck() async {
if (CurrentPlatform.isAndroid) {
final phonePermission = await Permission.phone.status;
if (phonePermission.isDenied) {
// Handle telephony interruptions only if permission is granted
await Permission.phone.request();
}
}
_handleMobileAudioInterruptions();
}
4. Explain permissions
Asking low level permissions, like READ_PHONE_STATE
might worry users. It is better to first get users onboarded and explain why you need this permission before requesting it.