zoukankan      html  css  js  c++  java
  • [Android Training视频系列] 8.2 Managing Audio Focus

    视频讲解:http://www.eyeandroid.com/thread-15896-1-1.html

    由于很多应用程序都可以播放音频,因此在播放前考虑它们如何交互就显得很重要了,为了避免同时出现多个声音,Android使用音频焦点(AudioFocus)来控制音频的播放 - 仅仅是获取到Audio Focus的应用程序才能够播放音频。

           在应用程序开始播放音频之前,它需要经过发出请求[request]à接受请求[receive] à音频焦点锁定[AudioFocus]的过程。同样它需要知道如何监听音频焦点的丢失并进行合适的响应。

           请求获取音频焦点

           在开始播放音频之前,应用程序必须先获取需要处理的音频流的音频焦点。音频焦点可以通过requestAudioFocus()方法获得,在音频焦点成功获取后,该方法会返回AUDIOFOCUS_REQUEST_GRANTED常量,否则会返回AUDIOFOCUS_REQUEST_FAILED常量。

           我们必须指定正在使用的是哪个音频流,而且是否想请求短暂还是永久的Audio Focus。短暂的焦点锁定:当期待播放一个短暂的音频的时候(比如播放导航指示);永久的焦点锁定:当计划播放可预期到的较长的音频的时候(比如播放音乐)。

           下面是一个在播放音乐的时候请求永久音频焦点的例子,我们必须在开始播放之前立即请求音频焦点,比如在用户点击播放或者游戏程序中下一关开始的片头音乐。

    AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);

    ...

    // Request audio focus for playback

    int result = am.requestAudioFocus(afChangeListener,// Use the music stream.

                                AudioManager.STREAM_MUSIC,// Request permanent focus.

                                AudioManager.AUDIOFOCUS_GAIN);

    if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {

        am.registerMediaButtonEventReceiver(RemoteControlReceiver);

        // Start playback.

    }

           一旦结束了播放,需要确保调用abandonAudioFocus()方法。这样会通知系统说你不再需要获取焦点并且取消注册AudioManager.OnAudioFocusChangeListener的监听。如果是释放短暂音频焦点的情况下,可以让之前被打断的应用程序继续播放。

    // Abandon audio focus when playback complete   

    am.abandonAudioFocus(afChangeListener);

           当请求短暂音频焦点的时候,我们可以选择是否开启“ducking”。Ducking是一个特殊的机制使得允许音频间歇性的短暂播放。

    通常情况下,一个好的应用程序在失去音频焦点的时候它会立即保持安静。如果我们选择在请求短暂音频焦点的时候开启了ducking,那意味着其它应用程序可以继续播放,仅仅是在这一刻降低自己的音量,在重新获取到音频焦点后恢复正常音量(也就是说:不用理会这个短暂焦点的请求,这并不会导致目前在播放的音频受到牵制,比如在播放音乐的时候突然出现一个短暂的短信提示声音,这个时候仅仅是把播放歌曲的音量暂时调低,好让短信声能够让用户听到,之后立马恢复正常播放)。

    // Request audio focus for playback

    int result = am.requestAudioFocus(afChangeListener,// Use the music stream.

                                 AudioManager.STREAM_MUSIC,// Request permanent focus.

                                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);

    if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {

        // Start playback.

    }

           Ducking非常适合间歇性播放音频的应用程序,例如播放导航仪的提示。

           当其他应用程序通过上述方式请求音频焦点时,您所注册的监听器可以判断是否获丢失了长期或短暂(可以选择是否支持Ducing)的音频焦点。

           处理失去音频焦点

           应用程序请求并得到音频焦点后,当其他应用程序请求焦点时,先前的应用程序就会失去焦点。您的应用程序需要根据失去音频焦点的类型来进行相应的处理。

           请求音频焦点时注册的音频焦点监听器中有onAudioFocusChange(int)回调函数,该回调函数会接收描述焦点变化事件的参数。需要注意的是,失去音频焦点的事件类型与请求焦点的类型相对应——失去长期焦点(AUDIOFOCUS_LOSS)、短暂焦点(AUDIOFOCUS_LOSS_TRANSIENT)和Ducking方式的短暂焦点(AUDIOFOCUS_LOSS_TRANSIENT)。

           失去短暂焦点:一般情况下,应用程序在失去短暂音频焦点时,应该停止播放并记录下播放状态。而且需要继续监听音频焦点的变化,当重新获得音频焦点时,需要在从先前暂停的地方继续播放。

           失去永久焦点:假设另外一个程序开始播放音乐等,那么我们的程序就应该有效的结束自己。实用的做法是停止播放,移除Media Button监听广播,允许新的音频播放器独占监听那些按钮事件,并且放弃自己的音频焦点。

           在下面的代码中,当应用程序失去短暂的音频焦点时会暂停播放,当重新获得焦点时会继续播放。当失去的是长期音频焦点时,就会取消媒体按键事件接收器的注册并停止对音频焦点变化的监听。

    OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {

        public void onAudioFocusChange(int focusChange) {

            if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT

                // Pause playback

            } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {

                // Resume playback

            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {

                am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);

                am.abandonAudioFocus(afChangeListener);

                // Stop playback

            }

        }

    };

           在上面失去短暂焦点的例子中,如果允许ducking,那么我们可以选择“duck”的行为而不是暂停当前的播放。

           闪避

           Ducking是一个特殊的机制使得允许音频间歇性地短暂播放。在Ducking的情况下,正常播放的歌曲会降低音量来凸显这个短暂的音频声音,这样既让这个短暂的声音比较突出,又不至于打断正常的声音。

           下面的代码会使应用程序在暂时失去焦点时降低媒体播放器的音量,并在重新获得音频焦点时恢复到原来的音量大小。

    OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {

        public void onAudioFocusChange(int focusChange) {

            if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {

                // Lower the volume

            } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {

                // Raise it back to normal

            }

        }

    };

           监听失去音频焦点是最重要的广播之一,但不是唯一需要监听的广播。系统广播了一系列的intent来警示你去改变用户的音频使用体验。下节课会演示如何监视那些广播来提升用户的整体体验。

  • 相关阅读:
    JavaScript的函数(二)
    Python:os.walk()和os.path.walk()用法
    Python:代码单元、代码点介绍
    Python:如何去掉字符串中不需要的字符
    Python:更改字典的key
    Python:如何对字符串进行左、右、居中对齐
    Python:format()方法
    日常开发之缓存技术
    Web系统大规模并发——秒杀与抢购 秒杀系统优化与预防措施
    PHP之位运算符
  • 原文地址:https://www.cnblogs.com/eyeandroid/p/3199732.html
Copyright © 2011-2022 走看看