天天看点

音量调节物理按键及音频焦点之AudioManager

在上一篇的音频播放提到了如何简单使用MediaPlayer,其中初始化的时候设置了固定的音量

mediaPlayer.setVolume(1.0f,1.0f)
           

这就导致了,我们在通过物理按键上下调节音量时,不起作用,若是不设置,播放的时候默认是固定系统音量之前设置好的那个媒体音量。也是不能通过物理按键上下调节音量。

问题出现,度娘出马,恍恍惚惚中发现可通过AudioManager来调节媒体音量,后来详细看了一下AudioManager的介绍,才发现这东西就是专门控制媒体音量的,包括铃声、闹钟和通话音量。

就我们这个问题来讲

首先通过

audioManager= (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
           

获得系统服务音量管理类AudioManager实例。

然后下面就意外的十分简单。

上调音量

audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,AudioManager.ADJUST_RAISE,AudioManager.FLAG_SHOW_UI);
           

下调音量

audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,AudioManager.ADJUST_LOWER,AudioManager.FLAG_SHOW_UI);
           

其中我们简单说一下上面参数的主要作用。

先看一下adjustStreamVolume方法的源码

public void adjustStreamVolume(int streamType, int direction, int flags) {
        final IAudioService service = getService();
        try {
            service.adjustStreamVolume(streamType, direction, flags,
                    getContext().getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
           

这里面我们主要是分析参数,有三个参数,从命名上不难看出streamType是代表音频分类,我们从源码中可以获取到有

很多种分类,这里就介绍几种

STREAM_VOICE_CALL(通话)

STREAM_SYSTEM(系统声音)

STREAM_RING(铃声)

STREAM_MUSIC(音乐)

STREAM_ALARM(闹铃)

而我们用的就是音乐类型。

第二个参数 direction 顾名思义就是方向,上下调节音量或者保持不变。

AudioManager.ADJUST_RAISE 就是上调一个音量
           
AudioManager.ADJUST_LOWER 就是下调一个音量
           

从源码中我们可以看到还有一个ADJUST_SAME 这个是指维持之前的音量不变,感觉和不设置我们最开始说的时候一样。

第三个参数 flags 可选标识。

我们代码中用的就是这个AudioManager.FLAG_SHOW_UI 显示出音量UI,就是上下调节音量时,会显示出音量UI让用户看到。
           

这里面还有几个就不多介绍了,有感兴趣的可以看源码,都介绍的很清楚。

这里我们在说下我们的主角AudioManager的几个使用方法。

我们可以通过setStreamVolume设置音量,通过getStreamVoume获得当前音量值,其中大小范围是0-7,设置为0,手机会自动设置为震动模式。

可以通过getStreamMaxVolume获取最大音量值,通过getStreamMinVolume获取最小音量值,此外这里我看网上说不同厂家的手机调节音量时的值也不同,这时候我们就可以通过获取最大值和最小值来通过自己分配一个变量来获取一个调试时的平均值,

当上下调节音量时就可以上下加减这个平均值,来达到适配。目前我没用这个,我觉得上面系统提供的方法已经满足了当前的需求。

对于AudioManager的功能还是很完善的,有兴趣了解更多的可以多看看源码。

最后根据我们通过物理按键上下调节音量改变系统音量。

在onKeyDown回调方法中

if(keyCode==KeyEvent.KEYCODE_VOLUME_UP){
    VoiceMediaPlayer.getInstance().addMediaVolume();
  }else if(keyCode==KeyEvent.KEYCODE_VOLUME_DOWN){
    VoiceMediaPlayer.getInstance().cutMediaVolume();
  }
           

这里的add和cut就是上面提到的增加减少音量的方法。

当第三方语音通话进来时,我们需要暂停播放,结束时,重新播放。

这里就涉及到了音频焦点的问题。

private AudioManager.OnAudioFocusChangeListener mAudioFocusChange=new AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            if(focusChange==AudioManager.AUDIOFOCUS_LOSS){//长时间丢失焦点
                isPauseOrPlay();
            }else if(focusChange==AudioManager.AUDIOFOCUS_LOSS_TRANSIENT){//短暂性丢失焦点
                isPauseOrPlay();
            }else if(focusChange==AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK){
                //短暂性丢失焦点并做降音处理
            }else if(focusChange==AudioManager.AUDIOFOCUS_GAIN){//其他应用申请焦点后又释放焦点后回调
                isPauseOrPlay();
            }
        }
    };
           
TelephonyManager telephonyManager= (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

telephonyManager.listen(new MyPhoneListener(), PhoneStateListener.LISTEN_CALL_STATE);
private final class MyPhoneListener extends android.telephony.PhoneStateListener{
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
                case TelephonyManager.CALL_STATE_RINGING://电话来了
                    VoiceMediaPlayer.getInstance().isPauseOrPlay();
                    break;
                case TelephonyManager.CALL_STATE_IDLE: //通话结束
                    VoiceMediaPlayer.getInstance().isPauseOrPlay();
                    break;
            }
        }
    }
           

第一段代码其实就可以通过焦点实现电话 第三方语音视频的监听。第二段是指针对手机电话的监听,这里只是贴出来看看。

继续阅读