捕获和丢弃音频焦点详细讲解

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/m0_37700275/article/details/79269250

目录介绍

  • 1.为什么要处理音频焦点问题
  • 1.1 发现问题说明
  • 1.2 为什么要处理音频焦点问题
  • 2.处理音频焦点逻辑
  • 2.1 伪代码逻辑思路
  • 2.2 请求和放弃音频焦点
  • 2.3 当音频焦点发生变化处理逻辑
  • 3.关于其他说明
  • 3.1 版本更新情况
  • 3.2 个人博客

好消息

  • 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计47篇[近20万字],转载请注明出处,谢谢!
  • 链接地址:https://github.com/yangchong211/YCBlogs
  • 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!

0.备注

1.为什么要处理音频焦点问题

1.1 发现问题说明

  • 如果手机上安装了两个音频播放器,当一个正在播放的时候,打开第二个播放歌曲,有没有发现第一个自动暂停了……
  • 如果你在听音频的同时,又去打开了其它视频APP,你会发现音频APP暂停播放了……
  • 如果你正在听音频或者看视频时,来电话了,那么音视频便会暂停。挂了电话后音乐又继续播放,视频则需要点击按钮播放,是不是很奇怪
  • 当你收到消息,比如微信消息,并且有消息声音的时候,那么听音频的那一瞬间,音频的声音会变小了,然后过会儿又恢复了。是不是很有意思。
  • 别蒙圈,这个就叫做音频捕获和丢弃焦点。
  • 至于如何处理,可以看我的源码案例: https://github.com/yangchong211/YCAudioPlayer
  • 还可以看我的博客,潇湘剑雨,博客大汇总: https://www.jianshu.com/p/53017c3fc75d

1.2 为什么要处理音频焦点问题

  • 如果不处理捕获与丢弃音频焦点的话,那么同时开几个音视频播放器,就会出现多个声音。那样会很嘈杂,一般线上的APP都会做这个处理,不过一些GitHub案例demo中一般没处理。

2.处理音频焦点逻辑

2.1 伪代码逻辑思路

  • 简单来说,就是这三步逻辑方法
  • 在service的oncreate方法中调用初始化方法
  • 在播放音频的时候开始请求捕获音频焦点
  • 在音频销毁的时候开始丢弃音频焦点

2.2 请求和放弃音频焦点

  • 当重新获得焦点的时候,如果通话结束,恢复播放;获取音量并且恢复音量。这个情景应该经常遇到。
  • 当永久丢失焦点,比如同时打开播放器,则停止或者暂停播放,否则出现两个声音
  • 当短暂丢失焦点,比如比如来了电话或者微信视频音频聊天等等,则暂停或者停止播放
  • 当瞬间丢失焦点,比如手机来了通知。前提是你的通知是震动或者声音时,会短暂地将音量减小一半。当然你也可以减小三分之一,哈哈!
  • 2.2.1 首先获取AudioManager对象
 mAudioManager = (AudioManager) content.getSystemService(AUDIO_SERVICE);
  • 2.2.2 请求和放弃音频焦点
  • AudioFocus这个其实是音频焦点,一般情况下音乐播放器都会处理这个音频焦点的,在其丢失音频焦点的情况会将音频暂停或者停止的逻辑的,等到再次获取到音频焦点的情况下会再次恢复播放的。
  • 音频获取焦点可以通过requestAudioFocus()方法获得,在音频焦点成功获取后,该方法会返回AUDIOFOCUS_REQUEST_GRANTED常量,否则,会返回AUDIOFOCUS_REQUEST_FAILED常量。
  • 音频失去焦点abandonAudioFocus()方法,这会通知系统您的App不再需要音频焦点,并移除相关OnAudioFocusChangeListener的注册。如果释放的是短暂音调焦点,那么被打断的音频会被继续播放。
  • 代码如下所示
/**
 * 请求音频焦点,开始播放时候调用
 * @return
 */
public boolean requestAudioFocus() {
	return mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
			AudioManager.AUDIOFOCUS_GAIN) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}

/**
 * 放弃音频焦点,销毁播放时候调用
 */
public void abandonAudioFocus() {
	mAudioManager.abandonAudioFocus(this);
}

2.3 当音频焦点发生变化处理逻辑

/**
 * 当音频焦点发生变化的时候调用这个方法,在这里可以处理逻辑
 * 欢迎访问我的GitHub:https://github.com/yangchong211
 * 如果可以的话,请star吧
 * @param focusChange       焦点改变
 */
@Override
public void onAudioFocusChange(int focusChange) {
	int volume;
	switch (focusChange) {
		// 重新获得焦点
		case AudioManager.AUDIOFOCUS_GAIN:
			if (!willPlay() && isPausedByFocusLossTransient) {
				// 通话结束,恢复播放
				mPlayService.playPause();
			}
			//获取音量
			volume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
			if (mVolumeWhenFocusLossTransientCanDuck > 0 && volume ==
					mVolumeWhenFocusLossTransientCanDuck / 2) {
				// 恢复音量
				mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
						mVolumeWhenFocusLossTransientCanDuck, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
			}

			isPausedByFocusLossTransient = false;
			mVolumeWhenFocusLossTransientCanDuck = 0;
			break;
		// 永久丢失焦点,如被其他播放器抢占
		case AudioManager.AUDIOFOCUS_LOSS:
			if (willPlay()) {
				forceStop();
			}
			break;
		// 短暂丢失焦点,比如来了电话或者微信视频音频聊天等等
		case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
			if (willPlay()) {
				forceStop();
				isPausedByFocusLossTransient = true;
			}
			break;
		// 瞬间丢失焦点,如通知
		case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
			// 音量减小为一半
			volume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
			if (willPlay() && volume > 0) {
				mVolumeWhenFocusLossTransientCanDuck = volume;
				mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
						mVolumeWhenFocusLossTransientCanDuck / 2,
						AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
			}
			break;
		default:
			break;
	}
}

3.关于其他说明

3.1 版本更新情况

  • v1.0.0 17年12月28日

3.2 个人博客

阅读更多

没有更多推荐了,返回首页