Android 仿微博列表视频(一),静音播放

新浪微博、QQ空间等一些 APP 有这样的效果(比较常见,就不截视频了):在列表页刷到一个视频的内容,视频自动播放,但是没有声音,如果你正在播放音乐,当视频播放的时候,音乐不会停止;如果点击视频,就进入下一个视频界面,这时候有声音了,播放的音乐也会停止。先说说这样的用户体验:像微博列表会有文字类、图片类、视频类,假如在公共场合突然刷到一个视频并且自动播放,有声音的情况:突然一个声音就冒出来了,然后大家都看着你;没有声音:静静的看着视频,如果感兴趣,带上耳机或者调低声音进入视频界面。

播放视频

一般播放视频要么是使用第三方的,也有自己封装 mediaplayer 的,先看看官方建议怎么使用 mediaplayer ;官方给出的是播放音频,视频一般采用的 mediaplayyer + textureview ,下面给出最简单代码,具体的自行搜索

mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource("yourVideoUrl");
//setSurface 主要是将mediaplayer 和textureview 联系起来,这里仅仅做演示,所以最简单化写出来
mMediaPlayer.setSurface(s);
mMediaPlayer.prepareAsync();
//几个监听事件        
mMediaPlayer.setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener);
mMediaPlayer.setOnCompletionListener(MediaPlayer.OnCompletionListener);
mMediaPlayer.setOnPreparedListener(MediaPlayer.OnPreparedListener);        

mMediaPlayer.setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener);

mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//开始播放
mMediaPlayer.start();

调节音量

MediaPlayer 本身提供了调节音量的 api : MediaPlayer.setVolume(float leftVolume, float rightVolume) ,取值范围是(0.0 - 1.0),leftVolume:左音量 ,rightVolume :右音量 。结合本文目的 — 静音,应该设置 :

mMediaPlayer.setVolume( 0f , 0f )

经过测试,的确达到了静音效果。微博视频还有这样的效果,其他APP正在播放音乐,假如在列表视频的时候设置静音,这个时候音乐不会受到影响,会继续播放,点击全屏的时候,音乐停止,播放视频的声音。这个效果怎么实现的呢,请看 AudioFocus

AudioFocus

先给出官网地址,也可以自行搜索,音频焦点:手机中有很多声音来源,如果有多个 APP 都同时播放音乐,这样的用户体验想想都怕,音频焦点的作用就是 APP 满足 一些特定条件,就可以获取音频焦点,就像微博播放视频的时候(全屏),音乐会自动停止,视频播放完毕,音乐就自动恢复(不是所有的音乐都会恢复,需要看播放音乐 APP 怎么处理的),这样的前提是播放音乐的 APP 也按照音频焦点。这里说说2个重要的条件

requestAudioFocus

代码使用

AudioManager audioManager = (AudioManager) getSystemService( AUDIO_SERVICE );
audioManager.requestAudioFocus( afChangeListener, AudioManager.STREAM_MUSIC,  
                               AudioManager.AUDIOFOCUS_GAIN_TRANSIENT );

请求音频焦点,获取音频焦点后,调节音量 setVolume 也会影响系统类型为 AudioManager.STREAM_MUSIC 的音量。官方建议播放完后释放音频焦点,也就是需要的时候就去请求焦点,不需要的就释放焦点

abandonAudioFocus

AudioManager audioManager = (AudioManager) getSystemService( AUDIO_SERVICE );
audioManager.abandonAudioFocus( afChangeListener)

释放焦点后,再调节音量 setVolume 就不会影响系统音量了。关于 AudioFocus 还有其他很多作用,具体搜索下,这里的目的主要是实现微博的效果,所以就不细讲。

微博列表静音,全屏恢复声音

思路也就明显了,也就是

列表静音: 播放释放假如有音频焦点就释放,并且设置 mMediaPlayer.setVolume( 0f , 0f );

全屏播放:全屏时候请求音频焦点,并且设置声音 mMediaPlayer.setVolume( 1f , 1f ) ,这里的数值看实际情况。

JieCaoVieoPlayer 实现静音

先说说有人说使用 mMediaPlayer.setVolume( ) 调节音量没有作用,据我实际使用中是有效果的,我想没有作用的情况应该是调用 setVolume 位置不对。在源码中

  mediaPlayer.release();
  mediaPlayer = new MediaPlayer();

这里出现在 JCMediaManager 类中 HANDLER_PREPARE 事件中,也就说,调用时间不对,在这个代码之前设置音量 并不会有作用,只有在 new MediaPlayer() 后 在下次 mediaPlayer.release() 前才有用,因为播放完一段视频或者播放下端视频都会调用 release。

为了不影响 JieCaoVieoPlayer 的源代码或者说以最小的改动实现我们的效果,我们需要继承之前使用的 JCVideoPlayer ,github 上面建议使用 JCVideoPlayerStandard ;如果要达到静音效果,我建议继承 JCVideoPlayerStandard ,并且在继承类添加下面的代码并复写部分代码;当然你也可以在你自己自定义中去添加部分代码。我这里偷懒,就在 demo 中的 mainActivity 中的 MyJCVideoPlayerStandard 设置,代码如下

      //静音模式  默认为false
      private boolean isSilencePattern = false;


     /**
     * 设置静音模式
     *
     * @param isSilencePattern
     */
     public void setSilencePattern(boolean isSilencePattern) {
        this.isSilencePattern = isSilencePattern;
     }

    /**
     * 设置音量
     *
     * @param isSilence
     */
     public void setVolume(boolean isSilence) {
        if (isSilence) {//静音
            JCMediaManager.instance().mediaPlayer.setVolume(0f, 0f);
        } else {
            JCMediaManager.instance().mediaPlayer.setVolume(1f, 1f);
        }

     }

    /**
     * 请求或者释放焦点
     *
     * @param focus
     */
    public void setAudioFocus(boolean focus) {
         AudioManager mAudioManager = (AudioManager) 
               getContext().getSystemService(Context.AUDIO_SERVICE);
        if (focus) {//请求音频焦点
            mAudioManager.requestAudioFocus(onAudioFocusChangeListener, 
                      AudioManager.STREAM_MUSIC,  
                      AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
        } else {//释放
            mAudioManager.abandonAudioFocus(onAudioFocusChangeListener);
        }
    }

现在就需要知道合理的位置调用合理的方法

焦点处理

在 JCVideoPlayer 中 startVideo 方法中,
这里写图片描述

出现了请求焦点,所以需要我们在子类中去复写 startVideo

    @Override
    public void startVideo() {
        super.startVideo();

        if (isSilencePattern) {
            setAudioFocus(false);
        }

    }

注意这添加的方法需要在 super.startVideo() 下面,如果放在上面会先执行 请求释放焦点,然后去执行 startVideo 中的请求焦点。

静音

上面也说了,需要在合适的位置调用才会生效,为了从一开始播放就静音,就找到开始播放前就设置静音,这里我选择的 onStatePlaying 这个方法,还有其他地方也可以,需要去看源码了解各个方法的作用复写。

     @Override
     public void onStatePlaying() {
        super.onStatePlaying();
        //在列表 或者 普通模式下,可以根据实际需求改变
        if (isSilencePattern && (currentScreen == SCREEN_LAYOUT_NORMAL ||  
        currentScreen == SCREEN_LAYOUT_LIST)) {
            setVolume(true);
        }
    }

当是全屏(或者小屏) 需要去请求音频焦点和设置音量,退出全屏(或小屏) 又恢复静音

    /**
     * 进入全屏
     */
    @Override
    public void startWindowFullscreen() {
        super.startWindowFullscreen();

        if (isSilencePattern) {
            setAudioFocus(true);
            setVolume(false);
        }
    }

退出全屏

    /**
     * 退出全屏
     */
    @Override
    public void playOnThisJcvd() {
        super.playOnThisJcvd();

        if (isSilencePattern) {
            setAudioFocus(false);
            setVolume(true);
        }
    }

经过上面几个步骤,普通列表静音,全屏恢复声音的效果就实现了,如果需要静音模式,在使用 JCVideoPlayerStandard 的时候 调用

mJCVideoPlayerStandard.setSilencePattern(true); 

也就加了几句话,就不上传代码了,需要的看看实现过程复制代码即可,时间匆忙,写的不是很清楚,请见谅并指出,这篇的思路来自群里的一位朋友,以前也想达到这种效果,也遇到设置 设置音量不管用,没有认真看源码,在没有经过严格测试下,也得出一些不可靠的结论,这里感谢那位朋友。

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页