Android EasyPlayer声音自动停止,恢复,一键静音等功能

  

<强> Android EasyPlayer声音自动停止,恢复,一键静音等功能

  

我们在开发播放器时,可能会需要静音或者降低音量的功能,比如说某款音乐播放器,当在后台播放时,如果此时有另外的系统通知声音发的出,可能播放器会把音量降低,系统声音结束后,再调高,如果有来电了,播放器可能会把音乐暂停,等通话结束后再继续播放。还有,比方说我们在某个场合放个视频,不料音量很大,会引来很多目光(很尴尬),这时候可能我们需要一键静音的功能。那这些功能我们应该如何实现呢?

  

Android播放声音的类为AudioTrack,播放器会先把音频流多路分配器出来,再解码,之后,把音频PCM数据通过AudioTrack类编写到音频设备中,从而通过话筒或者扬声器发出声音。

  

为了方便地实现声音控制,我们需要从应用的最上层进行操作(因为底层可能已经被抽象成库了),也就是要从AudioTrack来入手。让我们看看AudioTrack的一些API吧。

        int getPlayState ()   返回播放AudioTrack实例的状态。   获取当前的播放状态。这个接口会返回PLAYSTATE_STOPPED, PLAYSTATE_PAUSED PLAYSTATE_PLAYING   三种状态,分别表示未播放,暂停中,正在播放   之前            空白暂停()   暂停播放的音频数据。没有回放的数据不会被丢弃。后续调用玩()将这个数据。看到平()丢弃这些数据。   暂停播放音频数据。已经在缓冲区中的未播放数据将不会被丢弃,在下次玩的时候继续播放。调用冲水则会丢弃缓冲数据。   之前            空打()   发挥着AudioTrack开始。   开始播放   之前            int setStereoVolume (leftGain浮动,   浮动rightGain)      设置指定的左和右输出增益值>   mAudioEnable=mAudioTrack !=零,,mAudioTrack.getPlayState ()==PLAYSTATE_PLAYING;      公共空间setAudioEnable(布尔使){   mAudioEnable=启用;   在=mAudioTrack AudioTrack;   如果(在!=null) {   同步(){   如果(使){   at.pause ();   at.flush ();   其他}{   at.flush ();   at.play ();   }   }   }   }      之前      

注意这里在暂停之后,玩之前都调用了冲接口。这样可以确保在由暂停到播放切换时,不会把暂停时未播放的“旧数据“播放出来。

  

接下来我们实现音频资源被其它进程占用(失去焦点)时,自动降低声音或者停止声音;在音频资源又被释放(重新获取到焦点)时再恢复播放的功能。

  

我们需要通过AudioManager来判断当前音频资源的状态,并且在音频焦点更改时得到回调。其关键API接口有:

        int requestAudioFocus (AudioManager。OnAudioFocusChangeListener l,   int streamType,   int durationHint)   请求音频的焦点。发送一个请求来获取音频的焦点   请求获取音频焦点。   第一个参数为音频焦点更改时的回调;   第二个参数为音频类型,在我们调节音量时可以看到有若干种音量,就对应的这里的streamType,这里我们基本用音乐,表示“媒体”。   第三个参数表示获取焦点的“时”长,有如下几种情况:   AUDIOFOCUS_GAIN_TRANSIENT   表示仅仅为临时获取焦点。比如播放导航语音,通知声音等,属于时间很短暂的情况;   AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK   表示为鸭模式,表示当获取焦点后,允许先前获取过焦点的程序在降低输出音量的前提下继续播放。   AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE   痛第一种情况类似,只是不允许系统再播放其他声音。通常应用在语音备忘,语音识别等情况;   AUDIOFOCUS_GAIN   表示要获取焦点的时长未知。比如播放音乐等等。      当获取到焦点时,函数放回AUDIOFOCUS_REQUEST_GRANTED,当获取失败时,返回AUDIOFOCUS_REQUEST_FAILED      之前      

结合上面的API说明,参考如下代码以及解释:

     //获取AudioManager实例   最后AudioManager我=(AudioManager) mContext.getSystemService (Context.AUDIO_SERVICE);   AudioManager。OnAudioFocusChangeListener l=new AudioManager.OnAudioFocusChangeListener () {   @Override   公共空间onAudioFocusChange (int focusChange) {   如果(focusChange==AudioManager.AUDIOFOCUS_GAIN){//焦点获取到了,那继续播放,并恢复音量。   AudioTrack AudioTrack=mAudioTrack;   如果(audioTrack !=null) {   audioTrack.setStereoVolume (1.0, 1.0);   如果(audioTrack.getPlayState ()==AudioTrack.PLAYSTATE_PAUSED) {   audioTrack.flush ();   audioTrack.play ();   }   }   }else if (focusChange==AudioManager.AUDIOFOCUS_LOSS){//焦点丢失了,暂停播放。   AudioTrack AudioTrack=mAudioTrack;   如果(audioTrack !=null) {   如果(audioTrack.getPlayState ()==AudioTrack.PLAYSTATE_PLAYING) {   audioTrack.pause ();   }   }   }else if (focusChange==AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK){//焦点丢失了,但是允许在降低音量的前提下继续播放,那么降低声音。   AudioTrack AudioTrack=mAudioTrack;   如果(audioTrack !=null) {   audioTrack.setStereoVolume (0.5, 0.5);   }   }   }   };//因为这里要获得的焦点无法预知时长,因此用AUDIOFOCUS_GAIN模式。   int requestCode=udioManager requestAudioFocus (l。STREAM_MUSIC AudioManager.AUDIOFOCUS_GAIN);   如果(requestCode==AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {//成功获取到了焦点。那启动播放   AudioTrack AudioTrack=mAudioTrack;   如果(audioTrack !=null) {   audioTrack.setStereoVolume (1.0, 1.0);   如果(audioTrack.getPlayState ()==AudioTrack.PLAYSTATE_PAUSED) {   audioTrack.flush ();   audioTrack.play ();   }   }   其他}{//没有获取到音频焦点。那不播放声音   AudioTrack AudioTrack=mAudioTrack;   如果(audioTrack !=null) {   如果(audioTrack.getPlayState ()==AudioTrack.PLAYSTATE_PLAYING) {   audioTrack.pause ();   }   }   }   

Android EasyPlayer声音自动停止,恢复,一键静音等功能