Android MediaPlayer音频焦点问题,抢占声道

2024-03-05 07:08

本文主要是介绍Android MediaPlayer音频焦点问题,抢占声道,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

MediaPlayer既可以播放音频又可以播放视频,基本遇到的问题就是我在听音乐的时候播放音频或视频,出现了重叠的声音。这样对用户体验来说有些不太好,要控制别的应用是不可能的,所以只有去抢占声道了。当应用程序需要输出音频或通知的时候,需要请求音频焦点,当请求得到音频焦点之后,监听音频焦点的变换,当音频焦点变换了,根据返回回来的音频焦点码进行相应的处理。音频焦点的注册使用音频管理器的AudioManager.requestAudioFocus()方法设定。它的签名如下:
int requestAudioFocus(AudioManager.OnAudioFocusChangeListener l, int streamType, int durationHint)
这个方法的返回值是int类型,其含义被定义在AudioManager中以常量表示AUDIOFOCUS_REQUEST_FAILED(获取音频焦点失败)、AUDIOFOCUS_REQUEST_GRANTED(获取音频焦点成功)。其中重要的是第一个参数,为音频焦点变化的回调函数,在其中可以设定如果音频焦点变换了,当前应用如何管理MediaPlayer,第二个参数为媒体流的类型,第三个参数为持续的状态。
AudioManager.OnAudioFocusChangeListener为音频焦点变换的监听器,其中需要实现一个方法:onAudioFocusChange(int focusChange)在音频焦点变换的时候回调。它有一个参数,为当前表示音频焦点对于当前应用的状态码,通过这个状态码指定对应的操作,有些时候音频状态改变了,并不一定需要停止音频的播放。

 

AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() {public void onAudioFocusChange(int focusChange) {if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {// Pause playback} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {// Stop playback} else if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {// Lower the volume} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {// Resume playback or Raise it back to normal}}};  


focusChange有一下几种状态码:
AUDIOFOCUS_GAIN:获得音频焦点。
AUDIOFOCUS_LOSS:失去音频焦点,并且会持续很长时间。这是我们需要停止MediaPlayer的播放。
AUDIOFOCUS_LOSS_TRANSIENT:失去音频焦点,但并不会持续很长时间,需要暂停MediaPlayer的播放,等待重新获得音频焦点。
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:暂时失去音频焦点,但是无需停止播放,只需降低声音方法。

 

 

 

获取焦点后是必要要手动释放的。releaseTheAudioFocus()。这样当您的应用程序释放了音频焦点,则系统会允许其他被中断的应用程序重新获取该焦点来继续播放。

这里封装了一个工具类,只要直接使用即可:

 

import android.content.Context;
import android.media.AudioManager;
import android.os.Build;import com.maobang.imsdk.app.IMApplication;/*** Created by haijun on 2017/3/28.*/
public class AudioFocusManager {/*** 用AudioManager获取音频焦点避免音视频声音并发问题*/private AudioManager mAudioManager;private AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener;//zxzhong 请求音频焦点 设置监听public int requestTheAudioFocus(final AudioListener audioListener) {if (Build.VERSION.SDK_INT < 8) {//Android 2.2开始(API8)才有音频焦点机制return 0;}if (mAudioManager == null) {mAudioManager = (AudioManager) IMApplication.getContext().getSystemService(Context.AUDIO_SERVICE);}if (mAudioFocusChangeListener == null) {mAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {//监听器@Overridepublic void onAudioFocusChange(int focusChange) {switch (focusChange) {case AudioManager.AUDIOFOCUS_GAIN:case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK://播放操作audioListener.start();break;case AudioManager.AUDIOFOCUS_LOSS:case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK://暂停操作audioListener.pause();break;default:break;}}};}//下面两个常量参数试过很多 都无效,最终反编译了其他app才搞定,汗~int requestFocusResult = mAudioManager.requestAudioFocus(mAudioFocusChangeListener,AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);return requestFocusResult;}//zxzhong 暂停、播放完成或退到后台释放音频焦点public void releaseTheAudioFocus() {if (mAudioManager != null && mAudioFocusChangeListener != null) {mAudioManager.abandonAudioFocus(mAudioFocusChangeListener);}}public interface AudioListener{void start();void pause();}
}

具体使用方法:

 

1,实例一下AudioFocusManager audioFocusManager = new AudioFocusManager();

2,判断不为空时获取焦点,

 

if(audioFocusManager != null){//请求语音播放焦点int requestCode = audioFocusManager.requestTheAudioFocus(new AudioFocusManager.AudioListener() {@Overridepublic void start() {playVoice();//播放音频的方法}@Overridepublic void pause() {stop();}});if(requestCode == AudioManager.AUDIOFOCUS_REQUEST_GRANTED){playVoice();//播放音频的方法}}

 

 

 

3,音频播放完停止后,需要释放

 

 

 

 

if(audioFocusManager != null){audioFocusManager.releaseTheAudioFocus();}

 

 

 

 

 

 

 

 

 

这篇关于Android MediaPlayer音频焦点问题,抢占声道的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/775681

相关文章

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

SpringBoot内嵌Tomcat临时目录问题及解决

《SpringBoot内嵌Tomcat临时目录问题及解决》:本文主要介绍SpringBoot内嵌Tomcat临时目录问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录SprinjavascriptgBoot内嵌Tomcat临时目录问题1.背景2.方案3.代码中配置t

SpringBoot使用GZIP压缩反回数据问题

《SpringBoot使用GZIP压缩反回数据问题》:本文主要介绍SpringBoot使用GZIP压缩反回数据问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot使用GZIP压缩反回数据1、初识gzip2、gzip是什么,可以干什么?3、Spr

Android实现悬浮按钮功能

《Android实现悬浮按钮功能》在很多场景中,我们希望在应用或系统任意界面上都能看到一个小的“悬浮按钮”(FloatingButton),用来快速启动工具、展示未读信息或快捷操作,所以本文给大家介绍... 目录一、项目概述二、相关技术知识三、实现思路四、整合代码4.1 Java 代码(MainActivi

Android Mainline基础简介

《AndroidMainline基础简介》AndroidMainline是通过模块化更新Android核心组件的框架,可能提高安全性,本文给大家介绍AndroidMainline基础简介,感兴趣的朋... 目录关键要点什么是 android Mainline?Android Mainline 的工作原理关键

如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

《如何解决idea的Module:‘:app‘platform‘android-32‘notfound.问题》:本文主要介绍如何解决idea的Module:‘:app‘platform‘andr... 目录idea的Module:‘:app‘pwww.chinasem.cnlatform‘android-32

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2