Android AudioManager处理两个播放器同时有声音,停止其中一个播放的问题


 尽管某个时刻只有一个 activity 可以运行, Android 却是一个多任务环境.这对使用音频的应用带来了特殊的挑战,因为只有一个音频输出而可能多个媒体都想用它.在 Android2.2 之前,没有内建的机制来处理这个问题,所以可能在某些情况下导致坏的用户体验.例如,当一个用户正在听音乐而另一个应用需要通知用户一些重要的事情时,用户可能由于音乐声音大而不能听的通知.从 Android2.2 开始,平台为应用提供了一个协商它们如何使用设备音频输出的途径,这个机制叫做音频焦点,AudioManager。

    当你的应用需要输出像乐音和通知之类的音频时,你应该总是请求音频焦点.一旦应用具有了焦点,它就可以自由的使用音频输出.但它总是应该监听焦点的变化.如果被通知丢失焦点,它应该立即杀死声音或降低到静音水平(有一个标志表明应选择哪一个)并且仅当重新获得焦点后才恢复大声播放。

  首先,注册一个焦点监听器OnAudioFocusChangeListener 。

private AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener = null;
		//Build.VERSION.SDK_INT表示当前SDK的版本,Build.VERSION_CODES.ECLAIR_MR1为SDK 7版本 ,
		  //因为AudioManager.OnAudioFocusChangeListener在SDK8版本开始才有。
		if(Build.VERSION.SDK_INT > Build.VERSION_CODES.ECLAIR_MR1){
			mAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
				@Override
				public void onAudioFocusChange(int focusChange) {
					if(focusChange == AudioManager.AUDIOFOCUS_LOSS){
						//失去焦点之后的操作
						if(isPlaying()){
							pause();
						}
					}else if(focusChange == AudioManager.AUDIOFOCUS_GAIN){
						//获得焦点之后的操作
					}
				}
			};
		}

 

要请求音频焦点,你必须从AudioManager mAudioMgr调用requestAudioFocus(),如下所示:

private void requestAudioFocus() {
		if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.ECLAIR_MR1){
			return;
		}
		if (mAudioMgr == null)
			mAudioMgr = (AudioManager) ApplicationEx.app
					.getSystemService(Context.AUDIO_SERVICE);
		if (mAudioMgr != null) {
			DLog.i(TAG, "Request audio focus");
			int ret = mAudioMgr.requestAudioFocus(mAudioFocusChangeListener,
					AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
			if (ret != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
				DLog.i(TAG, "request audio focus fail. " + ret);
			}
		}

	}


放弃焦点

private void abandonAudioFocus() {
		if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.ECLAIR_MR1){
			return;
		}
		if (mAudioMgr != null) {

			DLog.i(TAG, "Abandon audio focus");

			mAudioMgr.abandonAudioFocus(mAudioFocusChangeListener);

			mAudioMgr = null;
		}
	}

参数focusChange告诉你音频焦点如何发生了变化,它可以是以上几种值(它们都是定义在AudioManager中的常量)

  • AUDIOFOCUS_GAIN:你已获得了音频焦点.

  • AUDIOFOCUS_LOSS:你已经丢失了音频焦点比较长的时间了.你必须停止所有的音频播放.因为预料到你可能很长时间也不能再获音频焦点,所以这里是清理你的资源的好地方.比如,你必须释放MediaPlayer

  • AUDIOFOCUS_LOSS_TRANSIENT:你临时性的丢掉了音频焦点,很快就会重新获得.你必须停止所有的音频播放,但是可以保留你的资源,因为你可能很快就能重新获得焦点.

  • AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:你临时性的丢掉了音频焦点,但是你被允许继续以低音量播放,而不是完全停止.

当第三方播放器也使用了这个机制的话,当你的应用获取声音焦点之后,第三方播放器失去焦点,做了暂停处理,即会停止播放。这样就不会出现两个播放器同时播放音乐的情况了。而如果第三方播放器没有经过处理,不管有没有焦点都一直播放,那就没有办法了。 =。=||

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Android中实现视频播放器可以通过以下步骤: 1. 在布局文件中添加一个SurfaceView用来展示视频: ``` <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 2. 在Activity中获取SurfaceView并设置MediaPlayer: ``` public class VideoPlayerActivity extends AppCompatActivity implements SurfaceHolder.Callback { private MediaPlayer mediaPlayer; private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_player); surfaceView = findViewById(R.id.surface_view); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); } @Override public void surfaceCreated(SurfaceHolder holder) { mediaPlayer.setDisplay(holder); try { mediaPlayer.setDataSource("video_path"); mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { mediaPlayer.release(); } } ``` 3. 添加控制按钮来控制视频播放: ``` public void play(View view) { mediaPlayer.start(); } public void pause(View view) { mediaPlayer.pause(); } public void stop(View view) { mediaPlayer.stop(); mediaPlayer.prepareAsync(); } ``` 需要注意的是,视频播放器的具体实现可能因应用场景不同而有所差异,例如添加进度条、全屏播放等功能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值