AudioManager这个音频管理器,它可以通过getSystemService得到。
(AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
方法介绍
setStreamVolume(int StreamType,int index,int flags):直接设置手机的指定类型的音量值
streamType 这个参数指定了声音的类型,如下
STREAM_ALARM:手机闹铃声音
STREAM_DTMF:DTMF音调的声音
STREAM_MUSIC:手机音乐的声音
STREAM_NOTFICATION:系统提示的声音
STREAM_RING:电话铃声的声音
STREAM_SYSTEM:手机系统的声音(不知道什么是系统声音,按键的声音?)
STREAM_VOICE_CALL:语音电话的声音
direction: 这个参数代表声音增大还是减少
flags:调整声音时的标志,例如指定FLAG_SHOW_UI,指定调整声音时显示音量进度条
- setMicrophoneMute(boolean on):设置是否让麦克风静音
- setMode(int mode):设置声音模式,可设置的值有NORMAL,RINGTONE和IN_CALL
setRingMode(int ringerMode):设置手机的电话铃声的模式
有如下集中几种
RINGER_MODE_NORMAL:正常手机铃声
RINGER_MODE_SILENT:手机铃声静音
RINGER_MODE_VIBRATE: 手机振动
setSpeakerphoneOn(boolean on):设置是否打开扩音器
知道了上述方法,还需要知道的一个点是播放媒体的时候请求音频焦点,退出播放后释放音频焦点。
/**
* 播放音乐前先请求音频焦点
*
* @return
*/
public boolean requestAudioFocus() {
return audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_REQUEST_GRANTED) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
/**
* 退出播放器后 不再占用音频焦点
*/
public void abandonAudioFocus() {
audioManager.abandonAudioFocus(this);
}
手机上避免不了会有其他媒体播放软件,所以会存在音频抢占的问题。因此在实现AudioManager.OnAudioFocusChangeListener
这个接口的时候 需要实现一个必须的方法onAudioFocusChange
。
在当前拥有音频焦点的情况下,有这么几个场景:
来电话,短暂丢失音频焦点
需要强制停止当前播放,
来短信,丢失瞬间的音频的焦点
将当前播放音乐音量减小为一半,等待重新获得音频焦点
通话结束,重新获得音频焦点
恢复播放
被其他播放器抢占,永久的丢失焦点
停止播放
实现如下:
public class AudioFocusManager implements AudioManager.OnAudioFocusChangeListener {
private final Context context;
private final IPlayControl control;
private final AudioManager audioManager;
// 短暂 音频焦点丢失 打电话
private boolean isPauseByFocusLossTransient;
// 瞬间 音频焦点丢失 很快就回来 来通知或者短信
private int mVolumeWhenFocusLossTransientCanDuck;
public AudioFocusManager(Context context, IPlayControl control) {
this.context = context;
this.control = control;
this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
/**
* 播放音乐前先请求音频焦点
*
* @return
*/
public boolean requestAudioFocus() {
return audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_REQUEST_GRANTED) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
/**
* 退出播放器后 不再占用音频焦点
*/
public void abandonAudioFocus() {
audioManager.abandonAudioFocus(this);
}
/**
* 音频焦点回调监听
*
* @param i
*/
@Override
public void onAudioFocusChange(int i) {
int volume;
switch (i) {
// 重新获得焦点
case AudioManager.AUDIOFOCUS_GAIN:
if (!willPlay() && isPauseByFocusLossTransient) {
// 通话结束,恢复播放
play();
}
volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
if (mVolumeWhenFocusLossTransientCanDuck > 0 && volume == mVolumeWhenFocusLossTransientCanDuck / 2) {
// 恢复音量
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mVolumeWhenFocusLossTransientCanDuck,
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
}
isPauseByFocusLossTransient = false;
mVolumeWhenFocusLossTransientCanDuck = 0;
break;
// 永久丢失焦点,如被其他播放器抢占
case AudioManager.AUDIOFOCUS_LOSS:
if (willPlay()) {
forceStop();
}
break;
// 短暂丢失焦点,如来电话
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (willPlay()) {
forceStop();
isPauseByFocusLossTransient = true;
}
break;
// 瞬间丢失焦点,如通知
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// 音量减小为一半
volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
if (willPlay() && volume > 0) {
mVolumeWhenFocusLossTransientCanDuck = volume;
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mVolumeWhenFocusLossTransientCanDuck,
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
}
break;
}
}
private void play() {
try {
control.resume();
} catch (RemoteException e) {
e.printStackTrace();
}
}
private void forceStop() {
try {
control.pause();
} catch (RemoteException e) {
e.printStackTrace();
}
}
private boolean willPlay() {
try {
return control.status() == PlayController.STATUS_PLAYING;
} catch (RemoteException e) {
e.printStackTrace();
return false;
}
}
}
参考文章