zoukankan      html  css  js  c++  java
  • 【转】关于音频焦点的理解

    什么叫音频焦点 (audio focus)?
      android系统是一个多任务操作系统,因此同一时刻允许许多任务同时工作。但是这对音频类应用来说是个挑战,因为如果多个音频同时播放的话,很多情况下用户体验会相当的差!比如听音乐时,来了个电话,这时你的耳机里就是电话和音乐共同工作,绝对是个悲剧!
      为了解决这个问题从android2.2开始引入audio focus的概念。当你需要播放音乐或者发送一个通知的时候,你可以去要求获得音频焦点。一旦获得,就可以自由的使用音频输出设备。但是同时它也在时时刻刻的监听着音频焦点的变化。当音频焦点变化时,你需要去合适的处理你的音频输出。
     
    音频焦点工作的示例:
    第一步
    首先你要获得一个音频管理服务AudioManager
            mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
    这个通常在service的oncreate中完成。
     
    第二步
    然后在合适的地方,比如播放音乐的按钮中放置获得音频焦点的代码
            mAudioManager.requestAudioFocus(mAudioFocusListener,
                    AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
    requestAudioFocus方法可以获得音频焦点,其有三个参数,解释如下:
    第一个参数 OnAudioFocusChangeListener:就是音频焦点变化时的监听器,这是音频焦点控制的重点。
    第二个参数streamType:焦点获得之后的数据传输类型,这里是AudioManager.STREAM_MUSIC
    第三个参数durationHint :告知系统,你要求获得音频焦点的用途,系统根据你所要求的类型来给其他监听者发出相应的焦点控制参数。有三种可选
          AUDIOFOCUS_GAIN_TRANSIENT:只是短暂获得,一会就释放焦点,比如你只是想发个notification时用下一秒不到的铃声。
         AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:只是背景获得,之前的音频焦点使用者无需释放焦点给我,我将与其共同使用。
         AUDIOFOCUS_GAIN:我要求完全获得焦点,其他人需要释放焦点。比如我要播放音乐了,这时就要抢占整个音频焦点。
     
    第三步
    实现音频焦点监听器OnAudioFocusChangeListener,这个监听器会根据当前音频焦点的变化,调用onAudioFocusChange(int focusChange)方法,focusChange主要有以下四种参数:
        AUDIOFOCUS_AGIN:你已经完全获得了音频焦点
        AUDIOFOCUS_LOSS:你会长时间的失去焦点,所以不要指望在短时间内能获得。请结束自己的相关音频工作并做好收尾工作。比如另外一个音乐播放器开始播放音乐了(前提是这个另外的音乐播放器他也实现了音频焦点的控制,baidu音乐,天天静听很遗憾的就没有实现,所以他们两个是可以跟别的播放器同时播放的)
        AUDIOFOCUS_LOSS_TRANSIENT:你会短暂的失去音频焦点,你可以暂停音乐,但不要释放资源,因为你一会就可以夺回焦点并继续使用
       AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:你的焦点会短暂失去,但是你可以与新的使用者共同使用音频焦点 
     
    具体示例如下:
     

    private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener(){
            public void onAudioFocusChange(int focusChange) {
                switch(focusChange){
                    case AudioManager.AUDIOFOCUS_LOSS:
                        if(isPlaying()){
                          //we do not need get focus back in this situation
                          //会长时间失去,所以告知下面的判断,获得焦点后不要自动播放
                            mPausedByTransientLossOfFocus = false;
                            pause();//因为会长时间失去,所以直接暂停
                        }
                        break;
                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                        if(isPlaying()){
                           //短暂失去焦点,先暂停。同时将标志位置成重新获得焦点后就开始播放
                            mPausedByTransientLossOfFocus = true;
                            pause();
                        }
                        break;
                    case AudioManager.AUDIOFOCUS_GAIN:
                        //重新获得焦点,且符合播放条件,开始播放
                        if(!isPlaying()&&mPausedByTransientLossOfFocus){
                            mPausedByTransientLossOfFocus = false;
                            resume();
                        }
                        break;
                }
            }};

        
    最后
    在适当的时候注销掉这个监听器比如在onDestroy()中
            mAudioManager.abandonAudioFocus(mAudioFocusListener);
    到此整个音频焦点的控制就完成了
     
     
      讲一个自己的故事,mPausedByTransientLossOfFocus 这个参数一开始没理解有什么作用,就没写。直到发现,我的音乐播放器在我已经手动暂停的情况下,总是在我打完电话后自动播放音乐,才发现他的作用。打完电话,手机就这么一路唱着歌在我的口袋里二逼呵呵的欢乐着。自己还不知道,等再要用手机的时候发现电都被搞掉了不少,且无数人侧目看我是一个怎样的二货喜欢外放音乐.....庆幸手机里没有凤凰传奇的歌曲。
      其实这个参数的作用就是可以让播放器仅仅在短暂失去音频焦点并重新获得后才开始播放音乐。而不是任何时候重新获得焦点都开始播放。

    from :https://blog.csdn.net/codemydream/article/details/53434891

  • 相关阅读:
    java反射并不是什么高深技术,面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象
    java反射意义
    vs2013中国集
    用户向导页面实现左右滑动的ImageSwitcher
    Java / Android H基于ttp多线程下载的实现
    成语接龙(dfs)
    python 弄github代码库列表
    leetcode先刷_Unique Paths II
    jquery于form正在使用submit问题,未解决
    Vs2012于Linux应用程序开发(2):图案
  • 原文地址:https://www.cnblogs.com/xuan52rock/p/10455598.html
Copyright © 2011-2022 走看看