音频焦点问题

Posted 王梦然

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了音频焦点问题相关的知识,希望对你有一定的参考价值。

当我们在settings中试听铃声,这时候突然来了一个电话,那么会出现试听铃声和来电铃声同时播放的情况。当然,此情况同样适用于闹钟铃声,媒体音乐播放等。那么怎么解决这个问题呢?这就需要当音频焦点。---》

因为系统中可能会有多个应用程序会播放音频,所以需要考虑他们之间该如何交互,为了避免多个应用程序同时播放音乐,android 系统使用音频焦点来进行统一管理,即只有获得了音频焦点的应用程序才可以播放音乐。 您的应用程序在开始播放音频文件前,首先应该请求获得音频焦点,并且应该同时注册监听音频焦点的丢失通知,即如果音频焦点被系统或其他的应用程序抢占时,您的应用程序可以做出合适的响应。

首先,我要获取一个音频焦点并管理它。

      private boolean requestFocus() {
        // Request audio focus for playback
        int result = mAudioManager.requestAudioFocus(afChangeListener,
                AudioManager.STREAM_RING,
                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
        return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
    }

  OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
        public void onAudioFocusChange(int focusChange) {
            if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
                    || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
                // Pause playback
                if (mLocalPlayer !=null && mLocalPlayer.isPlaying()){
                    mLocalPlayer.pause();
                }
            } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
                // Resume playback
                  startLocalPlayer();
            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
                mAudioManager.abandonAudioFocus(afChangeListener);
                // Stop playback
                if (mLocalPlayer !=null && mLocalPlayer.isPlaying()){
                    mLocalPlayer.stop();
                }
            }
        }
    };

可以很清晰的看见,上面的第一个方法是获取音频焦点,通过requestAudioFocus()来实现。而第二个方法就是对音频焦点进行监听并管理。在这里,要先知道以上几个值的含义:

  •      AUDIOFOCUS_GAIN_TRANSIENT:只是短暂获得,一会就释放焦点,比如你只是想发个notification时用下一秒不到的铃声。
  •      AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:只是背景获得,之前的音频焦点使用者无需释放焦点给我,我将与其共同使用。
  •      AUDIOFOCUS_GAIN:我要求完全获得焦点,其他人需要释放焦点。比如我要播放音乐了,这时就要抢占整个音频焦点。
  •      AUDIOFOCUS_LOSS:你会长时间的失去焦点,所以不要指望在短时间内能获得。请结束自己的相关音频工作并做好收尾工作。
  •     AUDIOFOCUS_LOSS_TRANSIENT:你会短暂的失去音频焦点,你可以暂停音乐,但不要释放资源,因为你一会就可以夺回焦点并继续使用。

知道了以上几个字段的含义,在对应的状态,我们就能做相应的处理。比如AUDIOFOCUS_LOSS_TRANSIENT短暂失去焦点,我们就暂停我们的音乐。AUDIOFOCUS_LOSS长期失去焦点,就直接停掉音乐。AUDIOFOCUS_GAIN我获取了焦点,那么我就要开始播放音乐了(由于我完全获取了焦点,其他音乐就无法播放了,自然当前就只有一个音乐进行播放)。

获取音频焦点,就要释放音频焦点:(在哪里释放,就看当时的代码吧)

    private void destroyLocalPlayer() {
        if (mLocalPlayer != null) {
            mLocalPlayer.reset();
            mLocalPlayer.release();
            mLocalPlayer = null;
            synchronized (sActiveRingtones) {
                sActiveRingtones.remove(this);
            }
        }
        mAudioManager.abandonAudioFocus(afChangeListener);
    }

在解决这个问题的时候,我选择在每次播放试听铃声时,获取音频焦点(何时获取,也要看当时代码情况):

    private void startLocalPlayer() {
        if (mLocalPlayer == null) {
            return;
        }
        synchronized (sActiveRingtones) {
            sActiveRingtones.add(this);
        }
        mLocalPlayer.setOnCompletionListener(mCompletionListener);
        if(requestFocus()){
            mLocalPlayer.start();
        }
    }

成功获取到焦点,才可以播放当前的试听铃声哦!

 

以上是关于音频焦点问题的主要内容,如果未能解决你的问题,请参考以下文章

管理音频焦点

音频焦点整理

片段变化后失去焦点(ANDROID TV)

Android TV - 在细节片段中失去焦点

当音频组件处于焦点时,从图像和音频列表中播放音频

Android 音频焦点管理