全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

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的都只能算是半成品,都有继续优化的余地。

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


# Android  # EasyPlayer声音自动停止、恢复  # 一键静音  # EasyPlayer声音的开发  # Vue2中easyplayer的使用教程详解  # Vue使用EasyPlayerPro播放本地MP4视频  # 在Vue3中使用EasyPlayer.js播放器的具体流程  # 播放器  # 一键  # 会把  # 时长  # 正在播放  # 回调  # 结束后  # 前提下  # 都有  # 第一个  # 却是  # 让我们  # 丢失了  # 很容易  # 我们可以  # 希望能  # 要想  # 第二个  # 很简单  # 仅为 


相关文章: 导航网站建站方案与优化指南:一站式高效搭建技巧解析  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  大学网站设计制作软件有哪些,如何将网站制作成自己app?  高端网站建设与定制开发一站式解决方案 中企动力  如何在腾讯云服务器快速搭建个人网站?  个人网站制作流程图片大全,个人网站如何注销?  常州自助建站工具推荐:低成本搭建与模板选择技巧  *服务器网站为何频现安全漏洞?  如何在VPS电脑上快速搭建网站?  济南专业网站制作公司,济南信息工程学校怎么样?  如何高效生成建站之星成品网站源码?  如何用狗爹虚拟主机快速搭建网站?  北京制作网站的公司排名,北京三快科技有限公司是做什么?北京三快科技?  免费公司网站制作软件,如何申请免费主页空间做自己的网站?  如何在IIS7中新建站点?详细步骤解析  php能控制zigbee模块吗_php通过串口与cc2530 zigbee通信【介绍】  如何选购建站域名与空间?自助平台全解析  西安专业网站制作公司有哪些,陕西省建行官方网站?  如何快速选择适合个人网站的云服务器配置?  php json中文编码为null的解决办法  如何快速查询网站的真实建站时间?  网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?  如何选择适合PHP云建站的开源框架?  如何通过.red域名打造高辨识度品牌网站?  临沂网站制作公司有哪些,临沂第四中学官网?  建站之星安装模板失败:服务器环境不兼容?  打鱼网站制作软件,波克捕鱼官方号怎么注册?  公众号网站制作网页,微信公众号怎么制作?  网站网页制作专业公司,怎样制作自己的网页?  手机怎么制作网站教程步骤,手机怎么做自己的网页链接?  ppt在线制作免费网站推荐,有什么下载免费的ppt模板网站?  建站之星如何助力企业快速打造五合一网站?  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  jQuery 常见小例汇总  seo网站制作优化,网站SEO优化步骤有哪些?  网站制作公司排行榜,抖音怎样做个人官方网站  官网网站制作腾讯审核要多久,联想路由器newifi官网  如何在IIS服务器上快速部署高效网站?  油猴 教程,油猴搜脚本为什么会网页无法显示?  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  建站之星后台密码遗忘如何找回?  高端企业智能建站程序:SEO优化与响应式模板定制开发  JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)  建站之星Pro快速搭建教程:模板选择与功能配置指南  如何在万网主机上快速搭建网站?  网站微信制作软件,如何制作微信链接?  如何通过西部数码建站助手快速创建专业网站?  模具网站制作流程,如何找模具客户?  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  建站之星安装提示数据库无法连接如何解决? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。