Skip to content

Commit dcc8f3d

Browse files
authored
Merge pull request #51 from GetStream/fix/audio-interruption-android-fix
fix: audio interruption on android
2 parents 2c953cc + 11316b5 commit dcc8f3d

File tree

6 files changed

+251
-224
lines changed

6 files changed

+251
-224
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
[2.2.0] - 2025-11-24
55
* Added `Helper.pauseAudioPlayout()` / `Helper.resumeAudioPlayout()` to mute and restore remote playback with platform-specific handling for iOS/macOS and Android.
6+
* [Android] Improved the audio focus handling for interruption purposes (`handleCallInterruptionCallbacks`). It now uses AudioSwitch and won't trigger unwanted interaction detections when focus is requested.
7+
- `androidAudioAttributesUsageType` and `androidAudioAttributesContentType` parameters in `handleCallInterruptionCallbacks` are now not needed and deprecated.
8+
* [Android] Added `regainAndroidAudioFocus` method that requests audio focus in case it was lost with no automatic regain.
69

710
[2.1.0] - 2025-11-17
811
* [iOS] Added Swift Package Manager (SPM) support to iOS.

android/src/main/java/io/getstream/webrtc/flutter/MethodCallHandlerImpl.java

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ static private void resultError(String method, String error, Result result) {
179179
}
180180

181181
void dispose() {
182+
if (AudioSwitchManager.instance != null) {
183+
AudioSwitchManager.instance.setAudioFocusChangeListener(null);
184+
}
182185
if (audioFocusManager != null) {
183186
audioFocusManager.setAudioFocusChangeListener(null);
184187
audioFocusManager = null;
@@ -413,58 +416,43 @@ public void onMethodCall(MethodCall call, @NonNull Result notSafeResult) {
413416
case "handleCallInterruptionCallbacks": {
414417
String interruptionSource = call.argument("androidInterruptionSource");
415418
AudioFocusManager.InterruptionSource source;
416-
417-
switch (interruptionSource) {
418-
case "audioFocusOnly":
419-
source = AudioFocusManager.InterruptionSource.AUDIO_FOCUS_ONLY;
420-
break;
421-
case "telephonyOnly":
422-
source = AudioFocusManager.InterruptionSource.TELEPHONY_ONLY;
423-
break;
424-
case "audioFocusAndTelephony":
425-
source = AudioFocusManager.InterruptionSource.AUDIO_FOCUS_AND_TELEPHONY;
426-
break;
427-
default:
428-
source = AudioFocusManager.InterruptionSource.AUDIO_FOCUS_AND_TELEPHONY;
429-
break;
430-
}
431-
432-
Integer usage = null, content = null;
433-
434-
// Prefer override values if provided, else fallback to persisted config
435-
String overrideUsageStr = call.argument("androidAudioAttributesUsageType");
436-
String overrideContentStr = call.argument("androidAudioAttributesContentType");
437419

438-
if (overrideUsageStr != null) {
439-
usage = AudioUtils.getAudioAttributesUsageTypeForString(overrideUsageStr);
440-
} else if (initializedAndroidAudioConfiguration != null) {
441-
usage = AudioUtils.getAudioAttributesUsageTypeForString(
442-
initializedAndroidAudioConfiguration.getString("androidAudioAttributesUsageType"));
420+
switch (interruptionSource) {
421+
case "audioFocusOnly":
422+
source = AudioFocusManager.InterruptionSource.AUDIO_FOCUS_ONLY;
423+
break;
424+
case "telephonyOnly":
425+
source = AudioFocusManager.InterruptionSource.TELEPHONY_ONLY;
426+
break;
427+
case "audioFocusAndTelephony":
428+
source = AudioFocusManager.InterruptionSource.AUDIO_FOCUS_AND_TELEPHONY;
429+
break;
430+
default:
431+
source = AudioFocusManager.InterruptionSource.AUDIO_FOCUS_AND_TELEPHONY;
432+
break;
443433
}
444434

445-
if (overrideContentStr != null) {
446-
content = AudioUtils.getAudioAttributesContentTypeFromString(overrideContentStr);
447-
} else if (initializedAndroidAudioConfiguration != null) {
448-
content = AudioUtils.getAudioAttributesContentTypeFromString(
449-
initializedAndroidAudioConfiguration.getString("androidAudioAttributesContentType"));
435+
if (audioFocusManager != null) {
436+
audioFocusManager.setAudioFocusChangeListener(null);
437+
audioFocusManager = null;
450438
}
451439

452-
audioFocusManager = new AudioFocusManager(context, source, usage, content);
440+
audioFocusManager = new AudioFocusManager(context, source);
453441

454442
audioFocusManager.setAudioFocusChangeListener(new AudioFocusManager.AudioFocusChangeListener() {
455-
@Override
456-
public void onInterruptionStart() {
457-
ConstraintsMap params = new ConstraintsMap();
458-
params.putString("event", "onInterruptionStart");
459-
FlutterWebRTCPlugin.sharedSingleton.sendEvent(params.toMap());
460-
}
443+
@Override
444+
public void onInterruptionStart() {
445+
ConstraintsMap params = new ConstraintsMap();
446+
params.putString("event", "onInterruptionStart");
447+
FlutterWebRTCPlugin.sharedSingleton.sendEvent(params.toMap());
448+
}
461449

462-
@Override
463-
public void onInterruptionEnd() {
464-
ConstraintsMap params = new ConstraintsMap();
465-
params.putString("event", "onInterruptionEnd");
466-
FlutterWebRTCPlugin.sharedSingleton.sendEvent(params.toMap());
467-
}
450+
@Override
451+
public void onInterruptionEnd() {
452+
ConstraintsMap params = new ConstraintsMap();
453+
params.putString("event", "onInterruptionEnd");
454+
FlutterWebRTCPlugin.sharedSingleton.sendEvent(params.toMap());
455+
}
468456
});
469457
result.success(null);
470458
break;
@@ -827,6 +815,19 @@ public void onInterruptionEnd() {
827815
result.success(null);
828816
break;
829817
}
818+
case "regainAndroidAudioFocus": {
819+
if (AudioSwitchManager.instance == null) {
820+
resultError("regainAndroidAudioFocus",
821+
"AudioSwitch manager is not initialized. Ensure plugin is attached before requesting focus.", result);
822+
break;
823+
}
824+
AudioSwitchManager.instance.requestAudioFocus();
825+
if (audioFocusManager != null) {
826+
audioFocusManager.notifyManualAudioFocusRegain();
827+
}
828+
result.success(null);
829+
break;
830+
}
830831
case "clearAndroidCommunicationDevice": {
831832
AudioSwitchManager.instance.clearCommunicationDevice();
832833
result.success(null);

0 commit comments

Comments
 (0)