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

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

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

Android播放声音的类为AudioTrack,播放器会先把音频流demux出来,再decode,之后,把音频PCM数据通过AudioTrack类write到音频设备中,从而通过话筒或者扬声器发出声音。

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

int getPlayState () Returns the playback state of the AudioTrack instance. 获取当前的播放状态。这个接口会返回PLAYSTATE_STOPPED、PLAYSTATE_PAUSED、PLAYSTATE_PLAYING 三种状态,分别表示未播放、暂停中、正在播放 void pause () Pauses the playback of the audio data. Data that has not been played back will not be discarded. Subsequent calls to play() will play this data back. See flush() to discard this data. 暂停播放音频数据。已经在缓冲区中的未播放数据将不会被丢弃,在下次play的时候继续播放。调用flush则会丢弃缓冲数据。 void play () Starts playing an AudioTrack. 开始播放 int setStereoVolume (float leftGain, float rightGain) Sets the specified left and right output gain values on the AudioTrack. 设置左右声道的音量增益。

有了这几个API,足以满足我们的需求。实现起来就非常简单了。

首先我们做一键静音功能。我们可以做个切换的按钮,这个按钮初始状态是要显示当前的播放状态:正在播放音频或未在播放音频。播放状态可以调用getPlayState ()来获取到;然后按钮按下后,再根据播放状态进行播放或暂停。

代码如下:

mAudioEnable = mAudioTrack!=null && mAudioTrack.getPlayState()==PLAYSTATE_PLAYING; public void setAudioEnable(boolean enable) { mAudioEnable = enable; AudioTrack at = mAudioTrack; if (at != null) { synchronized (at) { if (!enable) { at.pause(); at.flush(); } else { at.flush(); at.play(); } } } }

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

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

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

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

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

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

至此,我们便实现了EasyPlayer的声音自动停止、恢复,一键静音的功能的实现。看起来挺麻烦对吗?其实做一个app很容易,但是要想做的好,各种情况都兼顾了,却是很不容易的。我们不防多看些系统APP的实现,或者Google官方的一些DEMO,它们往往都看似功能很简单,会让我们觉得:“如果是我做的话,几行代码即可搞定。。”,但是它们的代码量却很大,因为它们兼顾了各种细节。而往往我们开发出来绝大多数app的都只能算是半成品,都有继续优化的余地。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

时间: 2024-10-27 16:58:26

Android EasyPlayer声音自动停止、恢复,一键静音等功能的相关文章

Android 7.1 内置“一键清理内存”功能,专治流氓勒索软件

本文讲的是Android 7.1 内置"一键清理内存"功能,专治流氓勒索软件, 在打击Android恶意勒索软件上,Google最近迈出了一大步,它推出的一项隐藏新功能,让用户在中招后还能保持对设备的控制权. XDA论坛的开发者发现,Android 7.1新增了一个紧急模式,可以通过连续四次短按后退按钮来触发.当激活紧急模式后,设备会回到桌面界面,关闭所有正在运行的应用程序,不受它们的锁定限制. 紧急模式连续短按的最大触发时间是0.3秒,也就是说,一秒内大概要按下四次后退按钮才能触发,

android-Android视频声音控制,videoview静音不影响系统音量的代码实现

问题描述 Android视频声音控制,videoview静音不影响系统音量的代码实现 Android中videoview能静音而不影响系统音量吗?如何做到? Android中有这样的视频组件吗?(不受系统音量影响,自己控制自己的音量) 解决方案 楼主解决了吗,我也遇到了这个问题 解决方案二: 楼主解决了吗?我现在也遇到了这个问题,同求解决方案!!! 解决方案三: 楼主解决了吗?我现在也遇到了这个问题,同求解决方案!!!

WinXP系统下创建一键静音快捷方式的操作

  小编经常使用电脑时发现,电脑右下角的喇叭按钮(音量图标)会无缘无关自己消失,有很多情况,可能会面临突发安静情况,我们都着急着静音,可是这时发现喇叭按钮不见了,那是的尴尬情况可想而知.或许有时,我们明明已经关掉了声音,但是当打开一个网站,可能还是会有声音发出,在那种安静的情况下,我们可能会惊慌失措,但如果有一个一键静音的方法,不管何时,都能讲杂音扼杀在摇篮里. WinXP系统下创建一键静音快捷方式的操作教程 1.首先,还是需要返回到winXP电脑的桌面位置,之后,找一个空白处,点击鼠标右键,在

怎样在电脑中设置一键静音快捷键

  1.首先,咱们还是需要返回到winXP电脑的桌面位置,之后,咱们找一个空白处,点击鼠标右键,在下滑菜单中选择新建-快捷方式. 2.之后会弹出一个创建快捷方式的窗口,咱们在项目位置这里填写"mmsys.cp",然后点击进入到下一步. 3.在新窗口中,需要用户来给咱们创建的快捷方式命名,大家只需要随意的取个名字就可以了,例如就叫一键静音即可. 完成之后,咱们就可以在winXP电脑的桌面位置看到这个图标了.

winXP系统下如何设置一键静音快捷键?

  1.首先,咱们还是需要返回到winXP电脑的桌面位置,之后,咱们找一个空白处,点击鼠标右键,在下滑菜单中选择新建-快捷方式. 2.之后会弹出一个创建快捷方式的窗口,咱们在项目位置这里填写"mmsys.cp",然后点击进入到下一步. 3.在新窗口中,需要用户来给咱们创建的快捷方式命名,大家只需要随意的取个名字就可以了,例如就叫一键静音即可.

Android简单记录和恢复ListView滚动位置的方法_Android

本文实例讲述了Android简单记录和恢复ListView滚动位置的方法.分享给大家供大家参考,具体如下: 有时候我们需要记录当前ListView滚动到的位置,重新加载的时候要回到原位,不罗嗦,给出代码: //列表滚动 private OnScrollListener ScrollLis = new OnScrollListener() { @Override public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3)

android生命周期-Android 绑定View的恢复,就是onRestoreInstanceState调用时

问题描述 Android 绑定View的恢复,就是onRestoreInstanceState调用时 好奇怪,发现Activity的onRestoreInstanceState调用后,尽是报空指针,发现之前绑定的View都没有绑定了,大家时如何恢复的? 解决方案 你要save之前的信息,如果没有这些信息,restore有什么意义

android各种声音类型级数设定及默认值

android各种声音类型级数设定及默认值            在audioservice.java文件中: /** @hide Maximum volume index values for audio streams */ private static final int[] MAX_STREAM_VOLUME = new int[] { 5, // STREAM_VOICE_CALL 7, // STREAM_SYSTEM 7, // STREAM_RING 15, // STREAM_

Android简单记录和恢复ListView滚动位置的方法

本文实例讲述了Android简单记录和恢复ListView滚动位置的方法.分享给大家供大家参考,具体如下: 有时候我们需要记录当前ListView滚动到的位置,重新加载的时候要回到原位,不罗嗦,给出代码: //列表滚动 private OnScrollListener ScrollLis = new OnScrollListener() { @Override public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3)