全网整合营销服务商

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

免费咨询热线: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播放器的具体流程  # 播放器  # 一键  # 会把  # 时长  # 正在播放  # 回调  # 结束后  # 前提下  # 都有  # 第一个  # 却是  # 让我们  # 丢失了  # 很容易  # 我们可以  # 希望能  # 要想  # 第二个  # 很简单  # 仅为 


相关文章: Bpmn 2.0的XML文件怎么画流程图  如何获取PHP WAP自助建站系统源码?  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  义乌企业网站制作公司,请问义乌比较好的批发小商品的网站是什么?  如何用虚拟主机快速搭建网站?详细步骤解析  杭州银行网站设计制作流程,杭州银行怎么开通认证方式?  网站好制作吗知乎,网站开发好学吗?有什么技巧?  如何选择可靠的免备案建站服务器?  建站之星安装后如何自定义网站颜色与字体?  购物网站制作公司有哪些,哪个购物网站比较好?  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  如何确认建站备案号应放置的具体位置?  C++用Dijkstra(迪杰斯特拉)算法求最短路径  个人摄影网站制作流程,摄影爱好者都去什么网站?  建站之星如何实现五合一智能建站与营销推广?  如何在万网自助建站中设置域名及备案?  如何用已有域名快速搭建网站?  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  如何在搬瓦工VPS快速搭建网站?  Swift中switch语句区间和元组模式匹配  婚礼视频制作网站,学习*后期制作的网站有哪些?  建站DNS解析失败?如何正确配置域名服务器?  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  如何在新浪SAE免费搭建个人博客?  如何选择美橙互联多站合一建站方案?  C#如何使用XPathNavigator高效查询XML  专业制作网站的公司哪家好,建立一个公司网站的费用.有哪些部分,分别要多少钱?  文字头像制作网站推荐软件,醒图能自动配文字吗?  c++怎么使用类型萃取type_traits_c++ 模板元编程类型判断【方法】  免费公司网站制作软件,如何申请免费主页空间做自己的网站?  html制作网站的步骤有哪些,iapp如何添加网页?  定制建站策划方案_专业建站与网站建设方案一站式指南  如何快速搭建高效服务器建站系统?  外汇网站制作流程,如何在工商银行网站上做外汇买卖?  沈阳个人网站制作公司,哪个网站能考到沈阳事业编招聘的信息?  TestNG的testng.xml配置文件怎么写  如何选择服务器才能高效搭建专属网站?  开封网站制作公司,网络用语开封是什么意思?  学校建站服务器如何选型才能满足性能需求?  建站主机如何选?高性价比方案全解析  已有域名如何快速搭建专属网站?  制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?  怎么将XML数据可视化 D3.js加载XML  XML的“混合内容”是什么 怎么用DTD或XSD定义  如何高效完成自助建站业务培训?  如何在IIS管理器中快速创建并配置网站?  如何在万网主机上快速搭建网站?  可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?  网页制作模板网站推荐,网页设计海报之类的素材哪里好?  如何用wdcp快速搭建高效网站? 

您的项目需求

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