Android 仿微博列表視頻(一),靜音播放

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 ,當然你也可以在你自己自定義中去添加部分代碼。我這裡偷懶,就在 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); 

You May Also Like