8000 feat: expose android audio modes (#1401) · liliBestCoder/flutter-webrtc@fad3b57 · GitHub
[go: up one dir, main page]

Skip to content

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fad3b57

Browse files
authored
feat: expose android audio modes (flutter-webrtc#1401)
* feat: expose android audio modes * fix imports
1 parent 12ea402 commit fad3b57

File tree

6 files changed

+190
-2
lines changed

6 files changed

+190
-2
lines changed

android/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ rootProject.allprojects {
1818
repositories {
1919
google()
2020
mavenCentral()
21+
maven { url 'https://jitpack.io' }
2122
}
2223
}
2324

@@ -52,7 +53,7 @@ android {
5253

5354
dependencies {
5455
implementation 'io.github.webrtc-sdk:android:114.5735.02'
55-
implementation 'com.twilio:audioswitch:1.1.7'
56+
implementation 'com.github.davidliu:audioswitch:fb33b237aa50b3d1d2dea0e0695ecb7b38a98971'
5657
implementation 'androidx.annotation:annotation:1.1.0'
5758
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
5859
}

android/src/main/java/com/cloudwebrtc/webrtc/MethodCallHandlerImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,11 @@ public void onMethodCall(MethodCall call, @NonNull Result notSafeResult) {
552552
result.notImplemented();
553553
}
554554
break;
555+
case "setAndroidAudioConfiguration": {
556+
Map<String, Object> configuration = call.argument("configuration");
557+
AudioSwitchManager.instance.setAudioConfiguration(configuration);
558+
break;
559+
}
555560
case "enableSpeakerphone":
556561
boolean enable = call.argument("enable");
557562
AudioSwitchManager.instance.enableSpeakerphone(enable);

android/src/main/java/com/cloudwebrtc/webrtc/audio/AudioSwitchManager.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
import java.util.Collections;
1919
import java.util.List;
2020
import java.util.Objects;
21+
import java.util.Map;
2122

2223
import kotlin.Unit;
2324
import kotlin.jvm.functions.Function2;
2425

2526
public class AudioSwitchManager {
27+
28+
public static final String TAG = "AudioSwitchManager";
29+
2630
@SuppressLint("StaticFieldLeak")
2731
public static AudioSwitchManager instance;
2832
@NonNull
@@ -52,6 +56,20 @@ public class AudioSwitchManager {
5256

5357
private boolean _speakerphoneOn = false;
5458

59+
/**
60+
* The audio focus mode to use while started.
61+
*
62+
* Defaults to [AudioManager.AUDIOFOCUS_GAIN].
63+
*/
64+
private int focusMode = AudioManager.AUDIOFOCUS_GAIN;
65+
66+
/**
67+
* The audio mode to use while started.
68+
*
69+
* Defaults to [AudioManager.MODE_NORMAL].
70+
*/
71+
private int audioMode = AudioManager.MODE_NORMAL;
72+
5573
public AudioSwitchManager(@NonNull Context context) {
5674
this.context = context;
5775
this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -74,6 +92,8 @@ private void initAudioSwitch() {
7492
audioFocusChangeListener,
7593
preferredDeviceList
7694
);
95+
audioSwitch.setFocusMode(focusMode);
96+
audioSwitch.setAudioMode(audioMode);
7797
audioSwitch.start(audioDeviceChangeListener);
7898
});
7999
}
@@ -160,4 +180,92 @@ public void selectAudioOutput(@Nullable AudioDeviceKind kind) {
160180
selectAudioOutput(kind.audioDeviceClass);
161181
}
162182
}
183+
184+
public void setAudioConfiguration(Map<String, Object> configuration) {
185+
if(configuration == null) {
186+
return;
187+
}
188+
189+
String audioMode = null;
190+
if (configuration.get("androidAudioMode") instanceof String) {
191+
audioMode = (String) configuration.get("androidAudioMode");
192+
}
193+
194+
String focusMode = null;
195+
if (configuration.get("androidAudioFocusMode") instanceof String) {
196+
focusMode = (String) configuration.get("androidAudioFocusMode");
197+
}
198+
199+
setAudioMode(audioMode);
200+
setFocusMode(focusMode);
201+
}
202+
203+
public void setAudioMode(@Nullable String audioModeString) {
204+
if (audioModeString == null) {
205+
return;
206+
}
207+
208+
int audioMode = -1;
209+
switch (audioModeString) {
210+
case "normal":
211+
audioMode = AudioManager.MODE_NORMAL;
212+
break;
213+
case "callScreening":
214+
audioMode = AudioManager.MODE_CALL_SCREENING;
215+
break;
216+
case "inCall":
217+
audioMode = AudioManager.MODE_IN_CALL;
218+
break;
219+
case "inCommunication":
220+
audioMode = AudioManager.MODE_IN_COMMUNICATION;
221+
break;
222+
case "ringtone":
223+
audioMode = AudioManager.MODE_RINGTONE;
224+
break;
225+
default:
226+
Log.w(TAG, "Unknown audio mode: " + audioModeString);
227+
break;
228+
}
229+
230+
// Valid audio modes start from 0
231+
if (audioMode >= 0) {
232+
this.audioMode = audioMode;
233+
if (audioSwitch != null) {
234+
Objects.requireNonNull(audioSwitch).setAudioMode(audioMode);
235+
}
236+
}
237+
}
238+
239+
public void setFocusMode(@Nullable String focusModeString) {
240+
if (focusModeString == null) {
241+
return;
242+
}
243+
244+
int focusMode = -1;
245+
switch(focusModeString) {
246+
case "gain":
247+
focusMode = AudioManager.AUDIOFOCUS_GAIN;
248+
break;
249+
case "gainTransient":
250+
focusMode = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT;
251+
break;
252+
case "gainTransientExclusive":
253+
focusMode = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE;
254+
break;
255+
case "gainTransientMayDuck":
256+
focusMode = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
257+
break;
258+
default:
259+
Log.w(TAG, "Unknown audio focus mode: " + focusModeString);
260+
break;
261+
}
262+
263+
// Valid focus modes start from 1
264+
if (focusMode > 0) {
265+
this.focusMode = focusMode;
266+
if (audioSwitch != null) {
267+
Objects.requireNonNull(audioSwitch).setFocusMode(focusMode);
268+
}
269+
}
270+
}
163271
}

lib/flutter_webrtc.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ export 'src/native/rtc_video_view_impl.dart'
1515
if (dart.library.html) 'src/web/rtc_video_view_impl.dart';
1616
export 'src/native/utils.dart' if (dart.library.html) 'src/web/utils.dart';
1717
export 'src/native/adapter_type.dart';
18+
export 'src/native/android/audio_configuration.dart';
19+
export 'src/native/ios/audio_configuration.dart';

lib/src/helper.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart';
22

33
import '../flutter_webrtc.dart';
44
import 'native/audio_management.dart';
5-
import 'native/ios/audio_configuration.dart';
65

76
class Helper {
87
static Future<List<MediaDeviceInfo>> enumerateDevices(String type) async {
@@ -122,6 +121,14 @@ class Helper {
122121
static Future<void> setMicrophoneMute(bool mute, MediaStreamTrack track) =>
123122
NativeAudioManagement.setMicrophoneMute(mute, track);
124123

124+
/// Set the audio configuration to for Android.
125+
/// Must be set before initiating a WebRTC session and cannot be changed
126+
/// mid session.
127+
static Future<void> setAndroidAudioConfiguration(
128+
AndroidAudioConfiguration androidAudioConfiguration) =>
129+
AndroidNativeAudioManagement.setAndroidAudioConfiguration(
130+
androidAudioConfiguration);
131+
125132
/// Set the audio configuration for iOS
126133
static Future<void> setAppleAudioConfiguration(
127134
AppleAudioConfiguration appleAudioConfiguration) =>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import 'package:flutter/foundation.dart';
2+
3+
import '../utils.dart';
4+
5+
enum AndroidAudioMode {
6+
normal,
7+
callScreening,
8+
inCall,
9+
inCommunication,
10+
ringtone,
11+
}
12+
13+
extension AndroidAudioModeExt on AndroidAudioMode {
14+
String get value => describeEnum(this);
15+
}
16+
17+
extension AndroidAudioModeEnumEx on String {
18+
AndroidAudioMode toAndroidAudioMode() => AndroidAudioMode.values
19+
.firstWhere((d) => describeEnum(d) == toLowerCase());
20+
}
21+
22+
enum AndroidAudioFocusMode {
23+
gain,
24+
gainTransient,
25+
gainTransientExclusive,
26+
gainTransientMayDuck,
27+
}
28+
29+
extension AndroidAudioFocusModeExt on AndroidAudioFocusMode {
30+
String get value => describeEnum(this);
31+
}
32+
33+
extension AndroidAudioFocusModeEnumEx on String {
34+
AndroidAudioFocusMode toAndroidAudioFocusMode() =>
35+
AndroidAudioFocusMode.values
36+
.firstWhere((d) => describeEnum(d) == toLowerCase());
37+
}
38+
39+
class AndroidAudioConfiguration {
40+
AndroidAudioConfiguration({
41+
this.androidAudioMode,
42+
this.androidAudioFocusMode,
43+
});
44+
final AndroidAudioMode? androidAudioMode;
45+
final AndroidAudioFocusMode? androidAudioFocusMode;
46+
47+
Map<String, dynamic> toMap() => <String, dynamic>{
48+
if (androidAudioMode != null)
49+
'androidAudioMode': androidAudioMode!.value,
50+
if (androidAudioFocusMode != null)
51+
'androidAudioFocusMode': androidAudioFocusMode!.value,
52+
};
53+
}
54+
55+
class AndroidNativeAudioManagement {
56+
static Future<void> setAndroidAudioConfiguration(
57+
AndroidAudioConfiguration config) async {
58+
if (WebRTC.platformIsAndroid) {
59+
await WebRTC.invokeMethod(
60+
'setAndroidAudioConfiguration',
61+
<String, dynamic>{'configuration': config.toMap()},
62+
);
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)
0