Android VidowView音频焦点问题

前言

好久没有发布文章了,整个5月底6月初的状态都在准备复习与面试的路上,最终选择了一家薪资待遇都不错的公司。之后会回忆一下面试相关的内容做一下复盘。

问题发现

目前公司的登录引导界面背景是无声视频,当然采用VideoView来加载视频。初到公司,熟悉业务,偶然间发现第三方音乐播放器播放音乐在后台,然后打开公司的App,启动引导页,发现音乐被暂停了。其实想想很简单,就是VideoView的焦点被获取了,直接取消获取音频焦点就万事大吉了。

解决问题

因为之前使用VideoView,一般都是有音乐的,没有注意到这个问题。找了找发现并没有能够取消获取音频焦点的Api,然后就看了看源码。

Android O 8.0 之前

private void openVideo() {
        if (mUri == null || mSurfaceHolder == null) {
            // not ready for playback just yet, will try again later
            return;
        }
        // we shouldn't clear the target state, because somebody might have
        // called start() previously
        release(false);
        // 1
        AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        //... 省略部分代码
}

1处代码可见,在我们setVideoURI的时候,会去调用openVideo()的方法,该方法在8.0之前会请求音频焦点,并且默认就是申请, 所以会导致其他正在播放的音频停止。

Android 8.0 之后

/**
     * Sets which type of audio focus will be requested during the playback, or configures playback
     * to not request audio focus. Valid values for focus requests are
     * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}. Or use
     * {@link AudioManager#AUDIOFOCUS_NONE} to express that audio focus should not be
     * requested when playback starts. You can for instance use this when playing a silent animation
     * through this class, and you don't want to affect other audio applications playing in the
     * background.
     * @param focusGain the type of audio focus gain that will be requested, or
     *    {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during playback.
     */
    public void setAudioFocusRequest(int focusGain) {
        if (focusGain != AudioManager.AUDIOFOCUS_NONE
                && focusGain != AudioManager.AUDIOFOCUS_GAIN
                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
            throw new IllegalArgumentException("Illegal audio focus type " + focusGain);
        }
        mAudioFocusType = focusGain;
    }

/**
     * Sets the {@link AudioAttributes} to be used during the playback of the video.
     * @param attributes non-null AudioAttributes.
     */
    public void setAudioAttributes(@NonNull AudioAttributes attributes) {
        if (attributes == null) {
            throw new IllegalArgumentException("Illegal null AudioAttributes");
        }
        mAudioAttributes = attributes;
    }
private void openVideo() {
        if (mUri == null || mSurfaceHolder == null) {
            // not ready for playback just yet, will try again later
            return;
        }
        // we shouldn't clear the target state, because somebody might have
        // called start() previously
        release(false);

        if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
            // TODO this should have a focus listener
            mAudioManager.requestAudioFocus(null, mAudioAttributes, mAudioFocusType, 0 /*flags*/);
        }
}

在8.0之后提供了setAudioFocusRequest()的方法,也支持在xml布局中设置。但是8.0之前怎么办呢?
解决方案就是因为业务需要,所以就可以复制一份VideoView源码,并且注释requestAudioFocus()的方法。

总结

问题很简单,不过其实文章目的是介绍一种方式方法,可以看Google工程师处理问题的解决方案,以及一些在ASOP中是怎样fix bug的。

  1. 首先 https://cs.android.com/ 这个是我用来看ASOP的网站。

    2.选择对应的版本,查看git提交记录。

    因此这个就是找到本期问题的方式方法,特此记录下。

你可能感兴趣的:(Android VidowView音频焦点问题)