简介
Audio通道有很多,Speaker、buletooth、headset等。在通话或者音乐播放的过程中,我们可能会发生Audio通道切换的情况。比如,插入有限耳机时,音频从耳机发出;拔出耳机的时候,Audio通道也会发生切换。如果我们不做对应的调整,那么可能会发生情况有,插入耳机时,音频从speaker中发出。因此我们要监听Audio通道变化,做对应的调整。
正文
Android中可以通过android.media.AudioManager查询当前的Audio输出的情况,并且在Audio输出发生变化时,捕获并处理这种变化。
需要的AudioManager的接口
public void startBluetoothSco()
public void stopBluetoothSco()
public boolean isBluetoothScoOn()
public void setBluetoothScoOn(boolean on)
public boolean isBluetoothA2dpOn()
public void startBluetoothScoVirtualCall()
public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
Audio输出状态查询及控制
- **isBluetoothScoOn() **: 检查A2DPAudio是否通过蓝牙耳机;
- isSpeakerphoneOn():检查扬声器是否打开;
- isWiredHeadsetOn():检查线控耳机是否连着;
Audio输出通道切换的事件的捕获与处理
这里是通过监听广播来捕获audio通道切换,如下代码:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_HEADSET_PLUG);
intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
private AudioManager audioManager;
@Override
public void onReceive(Context context, Intent intent) {
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
String action = intent.getAction();
if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", 0);
if (state == 0) { // 耳机拔出
Constants.changeToSpeaker(MicroContext.getApplication());
} else if (state == 1) { // 耳机插入
Constants.changeToReceiver(MicroContext.getApplication());
}
} else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
BluetoothHeadset.STATE_DISCONNECTED);
updateBluetoothIndication(state);
} else if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(action)) {
Constants.changeToSpeaker(MicroContext.getApplication());
}
}
public void updateBluetoothIndication(int bluetoothHeadsetState) {
if (bluetoothHeadsetState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "BluetoothProfile.STATE_CONNECTED");
if (audioManager == null) {
return;
} else {
Constants.changeToHeadset(MicroContext.getApplication());
}
} else if (bluetoothHeadsetState == BluetoothProfile.STATE_DISCONNECTING) {
if (audioManager == null) {
return;
} else {
Constants.changeToSpeaker(MicroContext.getApplication());
}
} else {
Log.i(TAG, "BluetoothProfile.OTHER");
}
}
/**
* 音频外放
*/
public static void changeToSpeaker(Context context) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
//注意此处,蓝牙未断开时使用MODE_IN_COMMUNICATION而不是MODE_NORMAL
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.stopBluetoothSco();
audioManager.setBluetoothScoOn(false);
audioManager.setSpeakerphoneOn(true);
}
/**
* 切换到蓝牙音箱
*/
public static void changeToHeadset(Context context) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
audioManager.setSpeakerphoneOn(false);
}
/**
* 切换到听筒
*/
public static void changeToReceiver(Context context) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
} else {
audioManager.setMode(AudioManager.MODE_IN_CALL);
}
}
有线耳机的插拔,Android中是通过广播ACTION_HEADSET_PLUG这个Intent通知的。当intent的"state"为1时,判断耳机插入,intent的"state"为0时,则判断耳机拔出。
蓝牙耳机的连接与断开,Android中时通过广播BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED这个Intent通知的,通过state的获取来判断蓝牙耳机是否连接,从而改变Audio通道
int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
BluetoothHeadset.STATE_DISCONNECTED);
public void updateBluetoothIndication(int bluetoothHeadsetState) {
if (bluetoothHeadsetState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "BluetoothProfile.STATE_CONNECTED");
if (audioManager == null) {
return;
} else {
Constants.changeToHeadset(MicroContext.getApplication());
}
} else if (bluetoothHeadsetState == BluetoothProfile.STATE_DISCONNECTING) {
if (audioManager == null) {
return;
} else {
Constants.changeToSpeaker(MicroContext.getApplication());
}
} else {
Log.i(TAG, "BluetoothProfile.OTHER");
}
}
耳机插拔、蓝牙耳机的断开,Audio输出通路也会自动切换,此时正在播放Audio的程序要获得通知,知道这一事件的发生。Android中是通过广播ACTION_AUDIO_BECOMING_NOISY这个Intent通知的。
小结
Audio 输出通道切换时,要根据具体需求来做相应的处理。