21 private static final String TAG =
"QtAudioDeviceManager";
22 static private AudioManager m_audioManager =
null;
23 static private final AudioDevicesReceiver m_audioDevicesReceiver =
new AudioDevicesReceiver();
24 static private Handler handler =
new Handler(Looper.getMainLooper());
25 static private AudioRecord m_recorder =
null;
26 static private AudioTrack m_streamPlayer =
null;
27 static private Thread m_streamingThread =
null;
28 static private boolean m_isStreaming =
false;
29 static private boolean m_useSpeaker =
false;
30 static private final int m_sampleRate = 8000;
31 static private final int m_channels = AudioFormat.CHANNEL_CONFIGURATION_MONO;
32 static private final int m_audioFormat = AudioFormat.ENCODING_PCM_16BIT;
33 static private final int m_bufferSize = AudioRecord.getMinBufferSize(m_sampleRate, m_channels, m_audioFormat);
38 static private void updateDeviceList() {
42 final AudioDeviceInfo[] audioDevices =
43 m_audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
44 setAudioOutput(getModeForSpeaker(audioDevices),
false,
true);
48 private static class AudioDevicesReceiver
extends AudioDeviceCallback {
50 public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
55 public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
63 m_audioManager.registerAudioDeviceCallback(m_audioDevicesReceiver, handler);
68 m_audioManager.unregisterAudioDeviceCallback(m_audioDevicesReceiver);
73 m_audioManager = (AudioManager)
context.getSystemService(Context.AUDIO_SERVICE);
76 private static String[] getAudioOutputDevices()
78 return getAudioDevices(AudioManager.GET_DEVICES_OUTPUTS);
81 private static String[] getAudioInputDevices()
83 return getAudioDevices(AudioManager.GET_DEVICES_INPUTS);
86 private static boolean isBluetoothDevice(AudioDeviceInfo deviceInfo)
88 switch (deviceInfo.getType()) {
89 case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
90 case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
97 private static boolean setAudioInput(MediaRecorder
recorder,
int id)
99 if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.P)
102 final AudioDeviceInfo[] audioDevices =
103 m_audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
105 for (AudioDeviceInfo deviceInfo : audioDevices) {
106 if (deviceInfo.getId() !=
id)
109 boolean isPreferred =
recorder.setPreferredDevice(deviceInfo);
110 if (isPreferred && isBluetoothDevice(deviceInfo)) {
111 m_audioManager.startBluetoothSco();
112 m_audioManager.setBluetoothScoOn(
true);
121 private static void setInputMuted(
boolean mute)
124 m_audioManager.setMicrophoneMute(mute);
127 private static boolean isMicrophoneMute()
129 return m_audioManager.isMicrophoneMute();
132 private static String audioDeviceTypeToString(
int type)
137 case AudioDeviceInfo.TYPE_AUX_LINE:
139 case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
140 case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
142 case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
143 return "Built in earpiece";
144 case AudioDeviceInfo.TYPE_BUILTIN_MIC:
145 return "Built in microphone";
146 case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
147 return "Built in speaker";
148 case AudioDeviceInfo.TYPE_DOCK:
150 case AudioDeviceInfo.TYPE_FM:
152 case AudioDeviceInfo.TYPE_FM_TUNER:
154 case AudioDeviceInfo.TYPE_HDMI:
156 case AudioDeviceInfo.TYPE_HDMI_ARC:
158 case AudioDeviceInfo.TYPE_IP:
160 case AudioDeviceInfo.TYPE_LINE_ANALOG:
161 return "Line analog";
162 case AudioDeviceInfo.TYPE_LINE_DIGITAL:
163 return "Line digital";
164 case AudioDeviceInfo.TYPE_TV_TUNER:
166 case AudioDeviceInfo.TYPE_USB_ACCESSORY:
167 return "USB accessory";
168 case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
169 return "Wired headphones";
170 case AudioDeviceInfo.TYPE_WIRED_HEADSET:
171 return "Wired headset";
175 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
176 if (
type == AudioDeviceInfo.TYPE_BUS)
180 return "Unknown-Type";
184 private static String[] getAudioDevices(
int type)
186 ArrayList<String>
devices =
new ArrayList<>();
188 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
189 boolean builtInMicAdded =
false;
190 boolean bluetoothDeviceAdded =
false;
191 for (AudioDeviceInfo deviceInfo : m_audioManager.getDevices(
type)) {
192 String
deviceType = audioDeviceTypeToString(deviceInfo.getType());
194 if (
deviceType.equals(audioDeviceTypeToString(AudioDeviceInfo.TYPE_UNKNOWN))) {
197 }
else if (
deviceType.equals(audioDeviceTypeToString(AudioDeviceInfo.TYPE_BUILTIN_MIC))) {
198 if (builtInMicAdded) {
207 builtInMicAdded =
true;
208 }
else if (isBluetoothDevice(deviceInfo)) {
209 if (bluetoothDeviceAdded) {
215 bluetoothDeviceAdded =
true;
219 + deviceInfo.getProductName().toString() +
")");
228 private static int getModeForSpeaker(AudioDeviceInfo[] audioDevices)
232 for (AudioDeviceInfo deviceInfo : audioDevices) {
233 switch (deviceInfo.getType()) {
234 case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
235 case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
236 case AudioDeviceInfo.TYPE_WIRED_HEADSET:
237 case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
238 return AudioManager.MODE_IN_COMMUNICATION;
242 return AudioManager.MODE_NORMAL;
246 private static boolean setAudioOutput(
int id)
248 m_useSpeaker =
false;
249 final AudioDeviceInfo[] audioDevices =
250 m_audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
251 for (AudioDeviceInfo deviceInfo : audioDevices) {
252 if (deviceInfo.getId() ==
id) {
253 switch (deviceInfo.getType())
255 case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
256 case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
257 setAudioOutput(AudioManager.MODE_IN_COMMUNICATION,
true,
false);
259 case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
261 setAudioOutput(getModeForSpeaker(audioDevices),
false,
true);
263 case AudioDeviceInfo.TYPE_WIRED_HEADSET:
264 case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
265 setAudioOutput(AudioManager.MODE_IN_COMMUNICATION,
false,
false);
267 case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
271 Log.w(TAG,
"Built in Earpiece may not work when "
272 +
"Wired Headphones are connected");
273 setAudioOutput(AudioManager.MODE_IN_CALL,
false,
false);
275 case AudioDeviceInfo.TYPE_HDMI:
276 case AudioDeviceInfo.TYPE_HDMI_ARC:
277 case AudioDeviceInfo.TYPE_HDMI_EARC:
278 setAudioOutput(AudioManager.MODE_NORMAL,
false,
false);
288 private static void setAudioOutput(
int mode,
boolean bluetoothOn,
boolean speakerOn)
290 m_audioManager.setMode(
mode);
292 m_audioManager.startBluetoothSco();
294 m_audioManager.stopBluetoothSco();
296 m_audioManager.setBluetoothScoOn(bluetoothOn);
297 m_audioManager.setSpeakerphoneOn(speakerOn);
301 private static void streamSound()
303 byte data[] =
new byte[m_bufferSize];
304 while (m_isStreaming) {
305 m_recorder.read(
data, 0, m_bufferSize);
306 m_streamPlayer.play();
307 m_streamPlayer.write(
data, 0, m_bufferSize);
308 m_streamPlayer.stop();
312 private static void startSoundStreaming(
int inputId,
int outputId)
315 stopSoundStreaming();
317 m_recorder =
new AudioRecord(MediaRecorder.AudioSource.DEFAULT, m_sampleRate, m_channels,
318 m_audioFormat, m_bufferSize);
319 m_streamPlayer =
new AudioTrack(AudioManager.STREAM_MUSIC, m_sampleRate, m_channels,
320 m_audioFormat, m_bufferSize, AudioTrack.MODE_STREAM);
322 final AudioDeviceInfo[]
devices = m_audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
323 for (AudioDeviceInfo deviceInfo :
devices) {
324 if (deviceInfo.getId() == outputId) {
325 m_streamPlayer.setPreferredDevice(deviceInfo);
326 }
else if (deviceInfo.getId() == inputId) {
327 m_recorder.setPreferredDevice(deviceInfo);
331 m_recorder.startRecording();
332 m_isStreaming =
true;
334 m_streamingThread =
new Thread(
new Runnable() {
340 m_streamingThread.start();
343 private static void stopSoundStreaming()
348 m_isStreaming =
false;
350 m_streamingThread.join();
351 m_streamingThread =
null;
352 }
catch (InterruptedException e) {
356 m_recorder.release();
357 m_streamPlayer.release();
358 m_streamPlayer =
null;