问题
I would like to change the sound device output in my Android app. I want to use the speaker of the phone when the headset plugged.
I've tried to use setSpeakerphoneOn from AudioManager classaudioManager.setSpeakerphoneOn(true);
with audioManager.setMode(AudioManager.MODE_IN_CALL);
but I don't want to set the MODE_IN_CALL ! I want to stay in MODE_NORMAL.
I've search around the AudioSystem class and I've found an application, "SoundAbout", which do that. You can choose the speaker for media audio and the mode stays in NORMAL.
So I've tried setDeviceConnectionState
in AudioSystem to set the DEVICE_OUT_WIRED_HEADPHONE to 0 but it doesn't work. When I check the status of DEVICE_OUT_WIRED_HEADPHONE, it's always set in 1 (AVAILABLE) and I can't play sound through the speaker.
How can I set DEVICE_OUT_WIRED_HEADPHONE to 0 or play sound through speaker without being in MODE_IN_CALL?
Thank's and sorry for my bad english !
回答1:
I try this and it's working for my case :
class AudioSystem {
private static final int REFLECTION_ERROR = -999;
private static final String DEVICE_OUT_SPEAKER = "DEVICE_OUT_SPEAKER";
private static final String DEVICE_OUT_EARPIECE = "DEVICE_OUT_EARPIECE";
private static final String DEVICE_OUT_WIRED_HEADPHONE = "DEVICE_OUT_WIRED_HEADPHONE";
Class<?> mAudioSystem;
protected AudioSystem() {
try {
mAudioSystem = Class.forName("android.media.AudioSystem");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private int getConstantValue(String s) {
try {
return ((Integer)mAudioSystem.getDeclaredField(s).get(int.class)).intValue();
} catch (Exception e) {
e.printStackTrace();
}
return REFLECTION_ERROR;
}
private int setDeviceConnectionState(int i, int j, String s) {
try {
return (Integer) mAudioSystem.getMethod("setDeviceConnectionState", int.class, int.class, String.class).invoke(mAudioSystem, i, j, s);
} catch (Exception e) {
e.printStackTrace();
}
return REFLECTION_ERROR;
}
private int setDeviceConnectionState(String deviceName, Boolean state) {
return setDeviceConnectionState(getConstantValue(deviceName), (state ? 1 : 0), "");
}
private void forceWiredHeadphonesMedia() {
setDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE, true);
setDeviceConnectionState(DEVICE_OUT_SPEAKER, false);
}
private void forceSpeakerMedia() {
setDeviceConnectionState(DEVICE_OUT_SPEAKER, true);
setDeviceConnectionState(DEVICE_OUT_EARPIECE, true);
setDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE, false);
setDeviceConnectionState(DEVICE_OUT_SPEAKER, true);
}
public void setSpeakerOn(Boolean state) {
if (state) {
forceSpeakerMedia();
} else {
forceWiredHeadphonesMedia();
}
}
}
I use setSpeakerOn(true)
to disable the wired headset.
Limit : AudioManager.isWiredHeadsetOn()
return false even the headset is plugged.
来源:https://stackoverflow.com/questions/29969030/android-force-audio-routing