一、Android音频开发(一):音频基础知识
二、Android音频开发(二):录制音频(WAV及MP3格式)
三、Android音频开发(三):使用ExoPlayer播放音频
四、Android音频开发(四):音频播放模式
五、Android音频开发(五):感应(息屏/亮屏)管理
附GitHub源码:MultimediaExplore
音频播放模式主要有:
1、耳机模式 2、外放模式 3、听筒模式
音频播放模式所需权限:
<!--音频模式切换权限-->
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
通过系统自带的 AudioManager 管理类来进行播放模式的切换,使用之前我们需初始化该类:
AudioManager audioManager = (AudioManager)appContext.getSystemService(Context.AUDIO_SERVICE);
然后设置其相应播放模式:
/**
* 切换到外放
*/
private void changeToSpeaker() {
if (audioManager != null) {
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setSpeakerphoneOn(true);
}
}
/**
* 切换到耳机模式
*/
private void changeToHeadset() {
if (audioManager != null) {
audioManager.setSpeakerphoneOn(false);
}
}
/**
* `
* 切换到听筒
*/
private void changeToReceiver() {
if (audioManager != null) {
audioManager.setSpeakerphoneOn(false);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
}
}
这里注意一点的是,我们需要监听耳机(包含有线耳机 / 蓝牙耳机)的插拔操作,系统专门的广播通知,我们需要注册监听广播如下:
//监听有线耳机
intentFilter.addAction(Intent.ACTION_HEADSET_PLUG);
intentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
//监听蓝牙耳机
intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
//注册监听耳机的插拔
appContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive -- 耳机");
String action = intent.getAction();
if (Objects.requireNonNull(action).equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", 0);
Log.d(TAG, "state:" + state);
if (state == 1) {
Log.d(TAG, "有线耳机插入");
playMode = PlayMode.Headset;
changeMode(playMode);
} else if (state == 0) {
Log.d(TAG, "有线耳机拔出");
if (isSpeakerOn()) {
playMode = PlayMode.Speaker;
} else {
playMode = PlayMode.Receiver;
}
changeMode(playMode);
}
} else if (action.equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
//此处 有线/蓝牙拔出状态应该均能监听到
Log.d(TAG, "有线耳机拔出");
} else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
switch (state) {
case BluetoothProfile.STATE_CONNECTED:
Log.d(TAG, "蓝牙耳机连接");
playMode = PlayMode.Headset;
changeMode(playMode);
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.d(TAG, "蓝牙耳机断开");
if (isSpeakerOn()) {
playMode = PlayMode.Speaker;
} else {
playMode = PlayMode.Receiver;
}
changeMode(playMode);
break;
}
}
}
}, intentFilter);
如上代码所示,根据需要的监听,自行添加即可。
另外,我们可能还需要得知当前耳机的已插入状态【比如我们插入/拔出耳机时还未打开APP无法接收到上面的广播通知】:
/**
* 耳机是否插入【有线耳机】
* @return
*/
public boolean isWiredHeadsetOn() {
if (audioManager == null) {
return false;
}
return audioManager.isWiredHeadsetOn();
}
/**
* 耳机是否插入【蓝牙耳机】
* @return
*/
public boolean isBlueToothHeadsetConnected() {
boolean result = true;
try {
result = BluetoothAdapter.getDefaultAdapter().getProfileConnectionState(android.bluetooth.BluetoothProfile.HEADSET)
!= android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
} catch (Exception ignored) {
}
return result;
}
最后,播放语音时还会涉及到与第三方音乐播放器音频焦点的抢夺:
/**
* 播放时语音时 调用该方法 屏蔽第三方音乐 同时使当前播放模式生效
*/
audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
/**
* 语音停止播放时 调用该方法 恢复第三方音乐播放 恢复播放模式
*/
audioManager.abandonAudioFocus(null);
另外,也可以结合APP前后台操作的监听,来控制当前音频的播放跟暂停等。
完整源码:
音频播放模式管理类-AudioModeManager源码