国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

完整視頻播放器封裝庫

feng409 / 1739人閱讀

摘要:可以支持多種視頻播放類型,比如,原生封裝視頻播放器,還有基于封裝的播放器。并且還支持刪除視頻播放位置狀態。拓展功能產品需求類似優酷,愛奇藝視頻播放器部分邏輯。

目錄介紹

1.關于此視頻封裝庫介紹

1.1 能夠滿足那些業務需求

1.2 對比同類型的庫有哪些優勢

2.關于使用方法說明

2.1 關于gradle引用說明

2.2 添加布局

2.3 最簡單的視頻播放器參數設定

2.4 注意的問題

2.5 關于開源庫中的類說明

3.關于播放類型說明

3.1 普通視頻播放

3.2 list頁面視頻播放

3.3 小窗口視頻播放

3.4 類似愛奇藝,優酷會員試看視頻播放

3.5 關于封裝庫中日志打印

4.關于相關方法說明

4.1 關于VideoPlayer類[播放器]中方法說明

4.2 關于VideoPlayerController類[控制器]中方法說明

4.3 關于對象的銷毀

5.關于封裝的思路

5.1 參考的案例思路

5.2 封裝的基本思路

5.3 關于窗口切換分析

5.4 關于VideoPlayerManager視頻播放器管理器分析

5.5 關于VideoPlayerController視頻控制器分析

5.6 關于InterVideoPlayer接口分析

6.關于如何自定義你想要的視頻播放模式

6.1 自定義視頻播放器

7.關于效果圖的展示

7.1 效果圖如下所示

8.關于遇到的問題說明

8.1 視頻難點

8.2 遇到的bug

8.3 后期需要實現的功能

9.關于版本更新說明

9.1 V1.0.0 更新于2017年9月4日

9.2 V1.0.1 更新于2017年11月18日

9.3 v1.1.0 更新于2018年1月15日

10.關于參考文檔說明

10.1 參考的項目

10.2 參考的博客

11.關其他說明

11.1 目前市場流行的視頻框架

11.2 如何選擇合適的框架

11.3 關于我的個人博客和站點

0.備注

仿照愛奇藝,優酷播放器寫的,十分感謝GitHub上大神前輩們的開源案例和思路。

支持插入廣告,設置視頻觀看權限,觀看完后登錄或者購買會員。我看到在star較多的項目issues中,有些人正好需要這個案例,庫集成后直接通過代碼調用即可,靈活且拓展性強。

由于調到做視頻的部門,因此此部分代碼會持續更新,也歡迎同行提bug或者問題

如果你覺得還可以,給個star吧!我也在持續學習中!!!

項目地址:https://github.com/yangchong2...

1.關于此視頻封裝庫介紹

1.1 能夠滿足那些業務需求

A基礎功能

1.1.1 能夠自定義視頻加載loading類型,設置視頻標題,設置視頻底部圖片,設置播放時長等基礎功能

1.1.2 可以切換播放器的視頻播放狀態,播放錯誤,播放未開始,播放開始,播放準備中,正在播放,暫停播放,正在緩沖等等狀態

1.1.3 可以自由設置播放器的播放模式,比如,正常播放,全屏播放,和小屏幕播放。其中全屏播放支持旋轉屏幕。

1.1.4 可以支持多種視頻播放類型,比如,原生封裝視頻播放器,還有基于ijkplayer封裝的播放器。

1.1.5 可以設置是否隱藏播放音量,播放進度,播放亮度等,可以通過拖動seekBar改變視頻進度。還支持設置n秒后不操作則隱藏頭部和頂部布局功能

-

B高級功能

1.1.6 支持一遍播放一遍緩沖的功能,其中緩沖包括兩部分,第一種是播放過程中緩沖,第二種是暫停過程中緩沖

1.1.7 基于ijkplayer的封裝播放器,支持多種格式視頻播放

1.1.8 可以設置是否記錄播放位置,設置播放速度,設置屏幕比例

1.1.9 支持滑動改變音量【屏幕右邊】,改變屏幕亮度【屏幕左邊】,支持切換視頻清晰度模式

1.1.0 支持list頁面中視頻播放,滾動后暫停播放,播放可以自由設置是否記錄狀態。并且還支持刪除視頻播放位置狀態。

-

C拓展功能

C1產品需求:類似優酷,愛奇藝視頻播放器部分邏輯。比如如果用戶沒有登錄也沒有看視頻權限,則提示試看視頻[自定義布局];如果用戶沒有登錄但是有看視頻權限,則正常觀看;如果用戶登錄,但是沒有充值會員,部分需要權限視頻則進入試看模式,試看結束后彈出充值會員界面;如果用戶余額不足,比如余額只有99元,但是視頻觀看要199元,則又有其他提示。

C2自身需求:比如封裝好了視頻播放庫,那么點擊視頻上登錄按鈕則跳到登錄頁面;點擊充值會員頁面也跳到充值頁面。這個通過定義接口,可以讓使用者通過方法調用,靈活處理點擊事件。

C.1.1 實現了上面兩個需求,靈活可拓展性強。

C.1.2 對于設置視頻的寬高,建議設置成4:3或者16:9或者常用比例,如果不是常用比例,則可能會有黑邊。其中黑邊的背景可以設置

C.1.3 可以設置播放有權限的視頻時的各種文字描述,而沒有把它寫在封裝庫中,使用者自己設定

C.1.4 鎖定屏幕功能

-

D待添加功能

D.1.1 可以支持屏幕截圖功能,視頻添加水印效果

D.1.2 支持彈幕功能

D.1.3 后期待定

1.2 對比同類型的庫有哪些優勢

1.2.1目前僅僅查了下GitHub上項目

目前GitHub上比較流行的庫

至于官方庫就不說了,jiecao的庫是基于ijkplayer視頻框架,目前封裝庫有許多,下面幾個只是star比較多,其中jiecao庫比較類似。

ijkplayer官方庫
https://github.com/Bilibili/ijkplayer
Vitamio官方庫
https://github.com/yixia/VitamioBundle
以jiecao為例的封裝庫
https://github.com/JasonChow1989/JieCaoVideoPlayer-develop          2年前
https://github.com/open-android/JieCaoVideoPlayer                   1年前
https://github.com/lipangit/JiaoZiVideoPlayer                       4個月前
https://github.com/CarGuo/GSYVideoPlayer
其他庫
https://github.com/danylovolokh/VideoPlayerManager

-

1.2.2 具有的優勢

A.代碼布局更加簡潔,而且無多余代碼

B.幾乎沒有多少淡黃色警告,關于注釋,通過使用阿里編碼插件檢測后更加規范,我對代碼有潔癖

C.視頻播放器[負責播放],視頻控制器[負責視頻播放各種點擊或者屬性設置操作],控制器抽象類[定義屬性抽象類,供子類實現],其他可以看代碼。結構分層上比較清晰

D.幾乎所有的方法或者重要的成員或者局部變量都有相關的注釋,注釋的內容非常詳細

E.關于視頻屬性設置或者按鈕點擊事件,都可以通過設置相關方法靈活實現。

首先這些庫封裝的思路和代碼都不錯,我也是借鑒他們的思路,在他們的思路上改進而封裝的。

相比來說代碼結構更加清晰,舉幾個例子

針對視頻播放頁面布局,由于視頻播放狀態眾多,我封裝這庫不同狀態布局有十幾種,許多庫的視圖布局沒注釋,顯示比較臃腫,如果修改或者定位,不熟悉或者好久不操作,都要花時間找。展示我的布局代碼



    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
2.關于使用方法說明

2.1 關于gradle引用說明

2.1.1直接引用這段代碼就可以

compile "cn.yc:YCVideoPlayerLib:2.2" 

2.2 添加布局

注意,在實際開發中,由于Android手機碎片化比較嚴重,分辨率太多了,建議靈活設置布局的寬高比為4:3或者16:9或者你認為合適的,可以用代碼設置。

如果寬高比變形,則會有黑邊

2.3 最簡單的視頻播放器參數設定

2.3.1 這個是最簡單視頻播放器的設置參數代碼

    //設置播放類型
    // IjkPlayer or MediaPlayer
    videoPlayer1.setPlayerType(VideoPlayer.TYPE_NATIVE);
    //網絡視頻地址
    String videoUrl = DataUtil.getVideoListData().get(0).getVideoUrl();
    //設置視頻地址和請求頭部
    videoPlayer1.setUp(videoUrl, null);
    //是否從上一次的位置繼續播放
    videoPlayer1.continueFromLastPosition(true);
    //設置播放速度
    videoPlayer1.setSpeed(1.0f);
    //創建視頻控制器
    VideoPlayerController controller = new VideoPlayerController(this);
    controller.setTitle("辦快來圍觀拉,自定義視頻播放器可以播放視頻拉");
    //設置視頻時長
    controller.setLength(98000);
    //設置5秒不操作后則隱藏頭部和底部布局視圖
    controller.setHideTime(5000);
    //controller.setImage(R.drawable.image_default);
    ImageUtil.loadImgByPicasso(this, R.drawable.image_default, R.drawable.image_default, controller.imageView());
    //設置視頻控制器
    videoPlayer1.setController(controller);

2.3.2 關于模仿愛奇藝登錄會員權限功能代碼

    //設置視頻加載緩沖時加載窗的類型,多種類型
    controller.setLoadingType(2);
    ArrayList content = new ArrayList<>();
    content.add("試看結束,yc觀看全部內容請開通會員1111。");
    content.add("試看結束,yc觀看全部內容請開通會員2222。");
    content.add("試看結束,yc觀看全部內容請開通會員3333。");
    content.add("試看結束,yc觀看全部內容請開通會員4444。");
    controller.setMemberContent(content);
    controller.setHideTime(5000);
    //設置設置會員權限類型,第一個參數是否登錄,第二個參數是否有權限看,第三個參數試看完后展示的文字內容,第四個參數是否保存進度位置
    controller.setMemberType(false,false,3,true);
    controller.imageView().setBackgroundResource(R.color.blackText);
    //ImageUtil.loadImgByPicasso(this, R.color.blackText, R.drawable.image_default, controller.imageView());
    //設置試看結束后,登錄或者充值會員按鈕的點擊事件
    controller.setOnMemberClickListener(new OnMemberClickListener() {
        @Override
        public void onClick(int type) {
            switch (type){
                case ConstantKeys.Gender.LOGIN:
                    //調到用戶登錄也米娜
                    startActivity(MeLoginActivity.class);
                    break;
                case ConstantKeys.Gender.MEMBER:
                    //調到用戶充值會員頁面
                    startActivity(MeMemberActivity.class);
                    break;
                default:
                    break;
            }
        }
    });

2.3.3其他設置,讓體驗更好

如果是在Activity中的話,建議設置下面這段代碼

    @Override
    protected void onStop() {
        super.onStop();
        VideoPlayerManager.instance().releaseVideoPlayer();
    }

    @Override
    public void onBackPressed() {
        if (VideoPlayerManager.instance().onBackPressed()) return;
        super.onBackPressed();
    }

如果是在Fragment中的話,建議設置下面這段代碼

    //在宿主Activity中設置代碼如下
    @Override
    protected void onStop() {
        super.onStop();
        VideoPlayerManager.instance().releaseVideoPlayer();
    }

    @Override
    public void onBackPressed() {
        if (VideoPlayerManager.instance().onBackPressed()) return;
        super.onBackPressed();
    }

    //--------------------------------------------------

    //在此Fragment中設置代碼如下
    @Override
    public void onStop() {
        super.onStop();
        VideoPlayerManager.instance().releaseVideoPlayer();
    }

2.4 注意的問題

2.4.1如果是全屏播放,則需要在清單文件中設置當前activity的屬性值

android:configChanges 保證了在全屏的時候橫豎屏切換不會執行Activity的相關生命周期,打斷視頻的播放

android:screenOrientation 固定了屏幕的初始方向

這兩個變量控制全屏后和退出全屏的屏幕方向

    

2.5 關于開源庫中的類說明

3.關于播放類型說明

3.1 普通視頻播放

3.1.1 這一步操作可以直接看第二部分內容——關于使用方法說明

3.2 list頁面視頻播放

3.2.1如何在list頁面設置視頻

第一步:在activity或者fragment中

    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setHasFixedSize(true);
    VideoAdapter adapter = new VideoAdapter(this, DataUtil.getVideoListData());
    recyclerView.setAdapter(adapter);
    //注意:下面這個方法不能漏掉
    recyclerView.setRecyclerListener(new RecyclerView.RecyclerListener() {
        @Override
        public void onViewRecycled(RecyclerView.ViewHolder holder) {
            VideoPlayer videoPlayer = ((VideoAdapter.VideoViewHolder) holder).mVideoPlayer;
            if (videoPlayer == VideoPlayerManager.instance().getCurrentVideoPlayer()) {
                VideoPlayerManager.instance().releaseVideoPlayer();
            }
        }
    });

第二步:在RecyclerView的適配器Adapter中

public class VideoAdapter extends RecyclerView.Adapter {

    private Context mContext;
    private List

3.3 小窗口視頻播放

3.3.1建議在設置小窗口先先判斷視頻播放器是否開始播放

    if (videoPlayer.isIdle()) {
        Toast.makeText(this, "要點擊播放后才能進入小窗口", Toast.LENGTH_SHORT).show();
    } else {
        videoPlayer.enterTinyWindow();
    }

3.4 類似愛奇藝,優酷會員試看視頻播放

3.4.1 可以參考——2.3.2 關于模仿愛奇藝登錄會員權限功能代碼

3.5 關于封裝庫中日志打印

3.5.1關于封裝庫中日志打印設置

如果上線產品后不想打印日志,可以在初始化時設置,注意需要在初始化播放器之前設置

    //如果不想打印庫中的日志,可以設置
    VideoLogUtil.isLog = false;

3.5.3關于日志工具類代碼

    public class VideoLogUtil {
    
        private static final String TAG = "YCVideoPlayer";
        public static boolean isLog = true;
    
        static void d(String message) {
            if(isLog){
                Log.d(TAG, message);
            }
    
        }
    
        static void i(String message) {
            if(isLog){
                Log.i(TAG, message);
            }
    
        }
    
        static void e(String message, Throwable throwable) {
            if(isLog){
                Log.e(TAG, message, throwable);
            }
        }
    }
4.關于相關方法說明

4.1 關于VideoPlayer類中方法說明

4.1.1 關于一定需要這四步

    //設置播放類型
    // IjkPlayer or MediaPlayer
    videoPlayer1.setPlayerType(VideoPlayer.TYPE_NATIVE);
    //設置視頻地址和請求頭部
    videoPlayer1.setUp(videoUrl, null);
    //創建視頻控制器
    VideoPlayerController controller = new VideoPlayerController(this);
    //設置視頻控制器
    videoPlayer1.setController(controller);

4.1.2 關于VideoPlayer中設置屬性方法

    //設置播放類型
    // MediaPlayer
    videoPlayer.setPlayerType(VideoPlayer.TYPE_NATIVE);
    // IjkPlayer
    videoPlayer.setPlayerType(VideoPlayer.TYPE_IJK);
    //網絡視頻地址
    String videoUrl = DataUtil.getVideoListData().get(1).getVideoUrl();
    //設置視頻地址和請求頭部
    videoPlayer.setUp(videoUrl, null);
    //是否從上一次的位置繼續播放
    videoPlayer.continueFromLastPosition(false);
    //設置播放速度
    videoPlayer.setSpeed(1.0f);
    //設置播放位置
    //videoPlayer.seekTo(3000);
    //設置音量
    videoPlayer.setVolume(50);

    //設置全屏播放
    videoPlayer.enterFullScreen();
    //設置小屏幕播放
    videoPlayer.enterTinyWindow();
    //退出全屏
    videoPlayer.exitFullScreen();
    //退出小窗口播放
    videoPlayer.exitTinyWindow();
    //釋放,內部的播放器被釋放掉,同時如果在全屏、小窗口模式下都會退出
    videoPlayer.release();
    //釋放播放器,注意一定要判斷對象是否為空,增強嚴謹性
    videoPlayer.releasePlayer();

4.1.3 關于VideoPlayer中獲取屬性方法

        //是否從上一次的位置繼續播放,不必須
        videoPlayer.continueFromLastPosition(false);
        //獲取最大音量
        int maxVolume = videoPlayer.getMaxVolume();
        //獲取音量值
        int volume = videoPlayer.getVolume();
        //獲取持續時長
        long duration = videoPlayer.getDuration();
        //獲取播放位置
        long currentPosition = videoPlayer.getCurrentPosition();
        //獲取緩沖區百分比
        int bufferPercentage = videoPlayer.getBufferPercentage();
        //獲取播放速度
        float speed = videoPlayer.getSpeed(1);

4.1.4 關于VideoPlayer中設置播放狀態方法

    //開始播放
    videoPlayer.start();
    //開始播放,從某位置播放
    videoPlayer.start(3000);
    //重新播放
    videoPlayer.restart();
    //暫停播放
    videoPlayer.pause();

4.1.5 關于VideoPlayer中獲取播放狀態方法

    //判斷是否開始播放
    boolean idle = videoPlayer.isIdle();
    //判斷視頻是否播放準備中
    boolean preparing = videoPlayer.isPreparing();
    //判斷視頻是否準備就緒
    boolean prepared = videoPlayer.isPrepared();
    //判斷視頻是否正在緩沖
    boolean bufferingPlaying = videoPlayer.isBufferingPlaying();
    //判斷是否是否緩沖暫停
    boolean bufferingPaused = videoPlayer.isBufferingPaused();
    //判斷視頻是否暫停播放
    boolean paused = videoPlayer.isPaused();
    //判斷視頻是否正在播放
    boolean playing = videoPlayer.isPlaying();
    //判斷視頻是否播放錯誤
    boolean error = videoPlayer.isError();
    //判斷視頻是否播放完成
    boolean completed = videoPlayer.isCompleted();
    //判斷視頻是否播放全屏
    boolean fullScreen = videoPlayer.isFullScreen();
    //判斷視頻是否播放小窗口
    boolean tinyWindow = videoPlayer.isTinyWindow();
    //判斷視頻是否正常播放
    boolean normal = videoPlayer.isNormal();

4.2 關于VideoPlayerController類[控制器]中方法說明

4.2.1 關于控制器方法

    //創建視頻控制器
    VideoPlayerController controller = new VideoPlayerController(this);
    //設置視頻標題
    controller.setTitle("高仿優酷視頻播放頁面");
    //設置視頻時長
    //controller.setLength(98000);
    //設置視頻加載緩沖時加載窗的類型,多種類型
    controller.setLoadingType(2);
    ArrayList content = new ArrayList<>();
    content.add("試看結束,觀看全部內容請開通會員1111。");
    content.add("試看結束,觀看全部內容請開通會員2222。");
    content.add("試看結束,觀看全部內容請開通會員3333。");
    content.add("試看結束,觀看全部內容請開通會員4444。");
    //設置會員權限話術內容
    controller.setMemberContent(content);
    //設置不操作后,5秒自動隱藏頭部和底部布局
    controller.setHideTime(5000);
    //設置設置會員權限類型,第一個參數是否登錄,第二個參數是否有權限看,第三個參數試看完后展示的文字內容,第四個參數是否保存進度位置
    controller.setMemberType(false,false,3,true);
    //設置背景圖片
    controller.imageView().setBackgroundResource(R.color.blackText);
    //ImageUtil.loadImgByPicasso(this, R.color.blackText, R.drawable.image_default, controller.imageView());
    //設置試看結束后,登錄或者充值會員按鈕的點擊事件
    controller.setOnMemberClickListener(new OnMemberClickListener() {
        @Override
        public void onClick(int type) {
            switch (type){
                case ConstantKeys.Gender.LOGIN:
                    //調到用戶登錄也米娜
                    startActivity(MeLoginActivity.class);
                    break;
                case ConstantKeys.Gender.MEMBER:
                    //調到用戶充值會員頁面
                    startActivity(MeMemberActivity.class);
                    break;
                default:
                    break;
            }
        }
    });
    //設置視頻清晰度
    //videoPlayer.setClarity(list,720);
    //設置視頻控制器
    videoPlayer.setController(controller);

4.3 關于對象的銷毀

4.3.1在VideoPlayer中如何釋放資源的呢?源代碼如下所示

    @Override
    public void release() {
        // 保存播放位置
        if (isPlaying() || isBufferingPlaying() || isBufferingPaused() || isPaused()) {
            VideoPlayerUtils.savePlayPosition(mContext, mUrl, getCurrentPosition());
        } else if (isCompleted()) {
            //如果播放完成,則保存播放位置為0,也就是初始位置
            VideoPlayerUtils.savePlayPosition(mContext, mUrl, 0);
        }
        // 退出全屏或小窗口
        if (isFullScreen()) {
            exitFullScreen();
        }
        if (isTinyWindow()) {
            exitTinyWindow();
        }
        mCurrentMode = MODE_NORMAL;

        // 釋放播放器
        releasePlayer();

        // 恢復控制器
        if (mController != null) {
            mController.reset();
        }
        // gc回收
        Runtime.getRuntime().gc();
    }
    //釋放播放器,注意一定要判斷對象是否為空,增強嚴謹性
    @Override
    public void releasePlayer() {
        if (mAudioManager != null) {
            //放棄音頻焦點。使以前的焦點所有者(如果有的話)接收焦點。
            mAudioManager.abandonAudioFocus(null);
            //置空
            mAudioManager = null;
        }
        if (mMediaPlayer != null) {
            //釋放視頻焦點
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        //從視圖中移除TextureView
        mContainer.removeView(mTextureView);
        if (mSurface != null) {
            mSurface.release();
            mSurface = null;
        }
        //如果SurfaceTexture不為null,則釋放
        if (mSurfaceTexture != null) {
            mSurfaceTexture.release();
            mSurfaceTexture = null;
        }
        //設置狀態
        mCurrentState = STATE_IDLE;
    }
5.關于封裝的思路

5.1 參考的案例思路

5.1.1目前參考的案例有

可以直接看下面的參考案例,有記錄

5.1.2針對jiaozi代碼簡單分析

JZVideoPlayer為繼承自FrameLayout實現的一個組合自定義View來實現了視頻播放器的View相關的內容。

JZVideoPlayerStandard則是繼承自JZVideoPlayer實現了一些自身的功能。

JZMediaManager是用來對于MediaPlayer的管理,對于MediaPlayer的一些監聽器方法的回調和TextrueView的相關回調處理。

JZVideoPlayerManager管理JZVideoPlayer

和自定義相關的工作,最主要是先繼承JCVideoPlayerStandard

JZMediaSystem主要是實現系統的播放引擎

不得不說,大神封裝代碼的思路以及代碼邏輯的確很強

關于封裝庫其他感受

第一:不過,感覺大神更新頻率大高,而且沒有找到每次更新的日志說明,不知道大神又解決了那些bug

第二:黃色警告多,而且注釋少,因為視頻封裝庫不像一般庫,有時候需求不同,可拓展性要求高。除了自己繼承JCVideoPlayerStandard創建視頻播放器,其他如果想改代碼,還是有點復雜的。

第三:關于使用雖然很簡單,但是在JZVideoPlayerStandard這個方法中,布局的對象都是用public修飾,如果你要想自己甚至某個控件背景或者圖標等等,則要這樣應用。如果你不去看看源代碼中布局名稱,你根本就不知道這個對象對應的是什么東西。對于不同修飾符,要合適的,如果不合適,那么就會有淡黃色警告。我看了buttonKnife,retrofit,阿里vlayout等等,可以說黃色警告很少……

  Picasso.with(this)
                .load("http://jzvd-pic.nathen.cn/jzvd-pic/1bb2ebbe-140d-4e2e-abd2-9e7e564f71ac.png")
                .into(jzVideo.thumbImageView);

5.2 封裝的基本思路

5.2.1關于簡單的思路分析

a1.可以把視頻播放和設置視頻屬性控制器分離,對于VideoPlayer中,各種UI狀態和操作反饋都封裝到VideoPlayerController控制器里面。如果需要根據不同的項目需求來修改播放器的功能,就只重寫VideoPlayerController就可以了。

a2.對于VideoPlayer這個類,可以先創建一個幀布局容器,然后在初始化的時候將視頻播放器控制器放到里面,然后通過設置控制器來進行視頻播放

a3.當調用了開始播放的方法后,就初始化播放器,包括原生的,還有IjkMediaPlayer

a4.而基于IjkMediaPlayer的視頻播放,需要添加各種監聽事件,通過閱讀IMediaPlayer源碼可以知道:可以在這些監聽事件中添加各種對視頻的操作邏輯,具體可以看代碼。

    void setOnPreparedListener(IMediaPlayer.OnPreparedListener var1);
    void setOnCompletionListener(IMediaPlayer.OnCompletionListener var1);
    void setOnBufferingUpdateListener(IMediaPlayer.OnBufferingUpdateListener var1);
    void setOnSeekCompleteListener(IMediaPlayer.OnSeekCompleteListener var1);
    void setOnVideoSizeChangedListener(IMediaPlayer.OnVideoSizeChangedListener var1);
    void setOnErrorListener(IMediaPlayer.OnErrorListener var1);
    void setOnInfoListener(IMediaPlayer.OnInfoListener var1);
    void setOnTimedTextListener(IMediaPlayer.OnTimedTextListener var1);

a5.定義好了監聽事件后,就創建了播放,重置播放,暫停等各種方法

5.3 關于窗口切換分析

5.3.1 關于窗口切換調用的代碼

    //設置全屏播放
    videoPlayer.enterFullScreen();
    //設置小屏幕播放
    videoPlayer.enterTinyWindow();
    //退出全屏
    videoPlayer.exitFullScreen();
    //退出小窗口播放
    videoPlayer.exitTinyWindow();
    //釋放,內部的播放器被釋放掉,同時如果在全屏、小窗口模式下都會退出
    videoPlayer.release();
    //釋放播放器,注意一定要判斷對象是否為空,增強嚴謹性
    videoPlayer.releasePlayer();

5.4 關于VideoPlayerManager視頻播放器管理器分析

5.4.1可以直接看源代碼,我對每個方法都有詳細的注釋

public class VideoPlayerManager {

    private VideoPlayer mVideoPlayer;
    private static VideoPlayerManager sInstance;
    private VideoPlayerManager() {}
    //一定要使用單例模式,保證同一時刻只有一個視頻在播放,其他的都是初始狀態
    public static synchronized VideoPlayerManager instance() {
        if (sInstance == null) {
            sInstance = new VideoPlayerManager();
        }
        return sInstance;
    }

    public VideoPlayer getCurrentVideoPlayer() {
        return mVideoPlayer;
    }

    void setCurrentVideoPlayer(VideoPlayer videoPlayer) {
        if (mVideoPlayer != videoPlayer) {
            releaseVideoPlayer();
            mVideoPlayer = videoPlayer;
        }
    }
    //當視頻正在播放或者正在緩沖時,調用該方法暫停視頻
    public void suspendVideoPlayer() {
        if (mVideoPlayer != null && (mVideoPlayer.isPlaying() || mVideoPlayer.isBufferingPlaying())) {
            mVideoPlayer.pause();
        }
    }
    //當視頻暫停時或者緩沖暫停時,調用該方法重新開啟視頻播放
    public void resumeVideoPlayer() {
        if (mVideoPlayer != null && (mVideoPlayer.isPaused() || mVideoPlayer.isBufferingPaused())) {
            mVideoPlayer.restart();
        }
    }
    //釋放,內部的播放器被釋放掉,同時如果在全屏、小窗口模式下都會退出
    public void releaseVideoPlayer() {
        if (mVideoPlayer != null) {
            mVideoPlayer.release();
            mVideoPlayer = null;
        }
    }
     //處理返回鍵邏輯.如果是全屏,則退出全屏 如果是小窗口,則退出小窗口
    public boolean onBackPressed() {
        if (mVideoPlayer != null) {
            if (mVideoPlayer.isFullScreen()) {
                return mVideoPlayer.exitFullScreen();
            } else if (mVideoPlayer.isTinyWindow()) {
                return mVideoPlayer.exitTinyWindow();
            }
        }
        return false;
    }
}

5.5 關于VideoPlayerController視頻控制器分析

5.5.1VideoPlayerController的作用

播放控制界面上,播放、暫停、播放進度、緩沖動畫、全屏/小屏等觸發都是直接調用播放器對應的操作的。

5.5.2VideoPlayerController的方法如下所示

    //創建視頻控制器
    VideoPlayerController controller = new VideoPlayerController(this);
    //設置視頻標題
    controller.setTitle("高仿優酷視頻播放頁面");
    //設置視頻時長
    //controller.setLength(98000);
    //設置視頻加載緩沖時加載窗的類型,多種類型
    controller.setLoadingType(2);
    ArrayList content = new ArrayList<>();
    content.add("試看結束,觀看全部內容請開通會員1111。");
    content.add("試看結束,觀看全部內容請開通會員2222。");
    content.add("試看結束,觀看全部內容請開通會員3333。");
    content.add("試看結束,觀看全部內容請開通會員4444。");
    //設置會員權限話術內容
    controller.setMemberContent(content);
    //設置不操作后,5秒自動隱藏頭部和底部布局
    controller.setHideTime(5000);
    //設置設置會員權限類型,第一個參數是否登錄,第二個參數是否有權限看,第三個參數試看完后展示的文字內容,第四個參數是否保存進度位置
    controller.setMemberType(false,false,3,true);
    //設置背景圖片
    controller.imageView().setBackgroundResource(R.color.blackText);
    //ImageUtil.loadImgByPicasso(this, R.color.blackText, R.drawable.image_default, controller.imageView());
    //設置試看結束后,登錄或者充值會員按鈕的點擊事件
    controller.setOnMemberClickListener(new OnMemberClickListener() {
        @Override
        public void onClick(int type) {
            switch (type){
                case ConstantKeys.Gender.LOGIN:
                    //調到用戶登錄也米娜
                    startActivity(MeLoginActivity.class);
                    break;
                case ConstantKeys.Gender.MEMBER:
                    //調到用戶充值會員頁面
                    startActivity(MeMemberActivity.class);
                    break;
                default:
                    break;
            }
        }
    });
    //設置視頻清晰度
    //videoPlayer.setClarity(list,720);
    //設置視頻控制器
    videoPlayer.setController(controller);

5.6 關于InterVideoPlayer接口分析

5.6.1關于此接口方法有

跟jiaozi代碼類似

    /**
     * 設置視頻Url,以及headers
     *
     * @param url           視頻地址,可以是本地,也可以是網絡視頻
     * @param headers       請求header.
     */
    void setUp(String url, Map headers);

    /**
     * 開始播放
     */
    void start();

    /**
     * 從指定的位置開始播放
     *
     * @param position      播放位置
     */
    void start(long position);

    /**
     * 重新播放,播放器被暫停、播放錯誤、播放完成后,需要調用此方法重新播放
     */
    void restart();

    /**
     * 暫停播放
     */
    void pause();

    /**
     * seek到制定的位置繼續播放
     *
     * @param pos 播放位置
     */
    void seekTo(long pos);

    /**
     * 設置音量
     *
     * @param volume 音量值
     */
    void setVolume(int volume);

    /**
     * 設置播放速度,目前只有IjkPlayer有效果,原生MediaPlayer暫不支持
     *
     * @param speed 播放速度
     */
    void setSpeed(float speed);

    /**
     * 開始播放時,是否從上一次的位置繼續播放
     *
     * @param continueFromLastPosition true 接著上次的位置繼續播放,false從頭開始播放
     */
    void continueFromLastPosition(boolean continueFromLastPosition);
6.關于如何自定義你想要的視頻播放模式

6.1 自定義視頻播放器

6.1.1如何自定義自己的播放器

第一步:首先繼承VideoPlayer這個類

第二步:然后重寫部分你需要更改功能的方法,只需要選擇你需要重寫的方法即可。

6.1.2代碼展示如下所示

    public class YCVideoPlayer extends VideoPlayer {

        public YCVideoPlayer(Context context) {
            super(context);
        }

        @Override
        public void setUp(String url, Map headers) {
            super.setUp(url, headers);
        }

        @Override
        public void setController(AbsVideoPlayerController controller) {
            super.setController(controller);
        }

        @Override
        public void setPlayerType(int playerType) {
            super.setPlayerType(playerType);
        }

        @Override
        public void continueFromLastPosition(boolean continueFromLastPosition) {
            super.continueFromLastPosition(continueFromLastPosition);
        }

        @Override
        public void setSpeed(float speed) {
            super.setSpeed(speed);
        }

        @Override
        public void start() {
            super.start();
        }

        @Override
        public void start(long position) {
            super.start(position);
        }

        @Override
        public void restart() {
            super.restart();
        }

        @Override
        public void pause() {
            super.pause();
        }

        @Override
        public void seekTo(long pos) {
            super.seekTo(pos);
        }

        @Override
        public void setVolume(int volume) {
            super.setVolume(volume);
        }

        @Override
        public boolean isIdle() {
            return super.isIdle();
        }

        @Override
        public boolean isPreparing() {
            return super.isPreparing();
        }

        @Override
        public boolean isPrepared() {
            return super.isPrepared();
        }

        @Override
        public boolean isBufferingPlaying() {
            return super.isBufferingPlaying();
        }

        @Override
        public boolean isBufferingPaused() {
            return super.isBufferingPaused();
        }

        @Override
        public boolean isPlaying() {
            return super.isPlaying();
        }

        @Override
        public boolean isPaused() {
            return super.isPaused();
        }

        @Override
        public boolean isError() {
            return super.isError();
        }
    }
7.關于效果圖的展示

7.1 效果圖如下所示











8.關于遇到的問題說明

8.1 視頻難點

8.1.1 當視頻切換全屏或者從全屏切換到正常小屏幕時,如何管理activity的生命周期

8.1.2 在列表list頁面,滑動顯示小窗口,那么什么時候顯示小窗口呢?關于RecyclerView的滑動位移超出屏幕有沒有更好的解決辦法?

8.1.2 當屏幕從全屏退出時,播放位置要滑到記錄的位置,代碼邏輯復雜,如何避免耦合度太高

8.2 遇到的bug

8.2.1 當視頻切花時,如何避免視頻不卡頓

8.2.2 在fragment中,當左右滑動出另一個fragment中,視頻還在播放,怎么樣處理這部分邏輯

8.2.3 在顯示緩沖比時,網絡不好或者暫停緩沖時有問題,所以暫停還沒有添加該功能

8.2.4 播放進度條seekbar跳動問題,有人反映不是那么順暢

8.2.5 部分華為手機播放視頻有問題,在找原因

8.2.6 在拖動時顯示當前幀的畫面圖片,類似優酷那個功能,最終還是沒有實現

8.3 后期需要實現的功能

8.3.1 如果有多集視頻,則添加上一集和下一集的功能

8.3.2 拖動滑動條,顯示幀畫面

8.3.3 實現彈幕功能

8.4.4 有些手機播放有問題,測試找問題

8.5.5 切換視頻清晰度有問題,是重新開始播放,因為切換清晰度時,調用的視頻鏈接是不同的。比如高清視頻和標準視頻鏈接是不同的,所以難以實現切換后記錄位置播放。但是看了下優酷,愛奇藝視頻,切換后是接著之前觀看的位置播放,這個需要思考下怎么實現。歡迎同行給出好的建議。

8.5.6 待定

9.關于版本更新說明

9.1 V1.0.0 更新于2017年10月4日

9.2 V1.0.1 更新于2017年11月18日

9.3 v1.1.0 更新于2018年1月15日

10.關于參考文檔說明

10.1 參考的項目

10.1.1參考的開源項目有

https://github.com/CarGuo/GSYVideoPlayer
https://github.com/danylovolokh/VideoPlayerManager
https://github.com/HotBitmapGG/bilibili-android-client
https://github.com/jjdxmashl/jjdxm_ijkplayer
https://github.com/JasonChow1989/JieCaoVideoPlayer-develop          2年前
https://github.com/open-android/JieCaoVideoPlayer                   1年前
https://github.com/lipangit/JiaoZiVideoPlayer                       4個月前
https://github.com/xiaoyanger0825/NiceVieoPlayer
https://github.com/curtis2/SuperVideoPlayer
https://github.com/tcking/GiraffePlayer

10.2 參考的博客

10.2.1參考的博客有"

https://segmentfault.com/a/1190000011959615
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1213/2153.html
http://blog.csdn.net/junwang19891012/article/details/8444743
https://www.jianshu.com/p/420f7b14d6f6
http://blog.csdn.net/candicelijx/article/details/39495271
11.關其他說明

11.1 目前市場流行的視頻框架

1.Android原生VideoView

2.Google 開源視頻播放框架 ExoPlayer

3.Vitamio 視頻播放框架

4.Bilibili 開源視頻播放框架ijkplayer

11.2 如何選擇

11.2.1.Android原生VideoView

1.1 VideoView 的使用非常簡單,播放視頻的步驟:

在界面布局文件中定義 VideoView 組件,或在程序中創建 VideoView 組件

調用 VideoView 的如下兩個方法來加載指定的視頻:

setVidePath(String path):加載 path 文件代表的視頻

setVideoURI(Uri uri):加載 uri 所對應的視頻

調用 VideoView 的 start()、stop()、psuse() 方法來控制視頻的播放

11.2.2.Google 開源視頻播放框架 ExoPlayer

2.1 框架地址:https://github.com/google/Exo...

2.2 用法

ExoPlayer 開源項目包含了 library 和 示例:

ExoPlayer library – 這部分是核心的庫

Demo app – 這部分是演示怎么使用 ExoPlayer 的 Demo

ExoPlayer 庫的核心類是 ExoPlayer 類。該類維護了播放器的全局狀態 。比如如何獲取媒體數據,如何緩沖以及是怎樣的編碼格式。

ExoPlayer 基于 MediaCodec 和 AudioTrack 提供了默認的音視頻的 TrackRenderer 實現。所有的 renderers 都需要 SampleSource 對象,ExoPlayer 從 SampleSource 獲得 media samples 用于播放。下圖展示了 ExoPlayer 是如何配置組合這些組件用于播放音視頻的。

standard-model

ExoPlayer 庫提供了一些不同類型的 SampleSource 實例:

ExtractorSampleSource – 用于 MP3,M4A,WebM,MPEG-TS 和 AAC;

ChunkSampleSource – 用于 DASH 和平滑流的播放;

HlsSampleSource – 用于 HLS 播放;

在 ExoPlayer 的 Dome 中使用 DemoPlayer 對 ExoPlayer 進行了封裝,并提供了使用上述幾種 SampleSource 構建 TrackRenderer 的 Builder。

SmoothStreamingRendererBuilder

DashRendererBuilder

ExtractorRendererBuilder

在使用的時候我們根據不同的需求創建對應的 RendererBuilder,然后將 RendererBuilder 傳遞給 DemoPlayer 然后調用 DemoPlayer 的 setPlayWhenReady 方法。

2.3 優缺點

ExoPlayer 相較于 MediaPlayer 有很多很多的優點:

支持動態的自適應流 HTTP (DASH) 和 平滑流,任何目前 MediaPlayer 支持的視頻格式(同時它還支持 HTTP 直播(HLS),MP4,MP3,WebM,M4A,MPEG-TS 和 AAC)。

支持高級的 HLS 特性,例如正確處理 EXT-X-DISCONTINUITY 標簽;

支持自定義和擴治你的使用場景。ExoPlayer 專門為此設計;

便于隨著 App 的升級而升級。因為 ExoPlayer 是一個包含在你的應用中的庫,對于你使用哪個版本有完全的控制權,并且你可以簡單的跟隨應用的升級而升級;

更少的適配性問題。

ExoPlayer 的缺點:

ExoPlayer 的音頻和視頻組件依賴 Android 的 MediaCodec 接口,該接口發布于 Android4.1(API 等級 16)。因此它不能工作于之前的Android 版本。

11.2.3.Vitamio 視頻播放框架

3.1 用法

官網:https://www.vitamio.org

Vitamio 的使用步驟:

1.下載 Vitamio 庫,并作為工程依賴。

2.在 Activity 的 onCreate 方法中添加如下代碼,初始化 Vitamio 的解碼器

3.2 優點

強大,支持超多格式視頻和網絡視頻播放。

使用簡單。調用非常簡單,方便使用。

其官方還給出了其他很多優點,但是個人覺得不足以成為優點。

11.2.4.Bilibili 開源視頻播放框架ijkplayer

4.1 特點

HTTPS支持

支持彈幕

支持基本的拖動,聲音、亮度調節

支持邊播邊緩存

支持視頻本身自帶rotation的旋轉(90,270之類),重力旋轉與手動旋轉的同步支持

支持列表播放,直接添加控件為封面,列表全屏動畫,視頻加載速度,列表小窗口支持拖動

5.0的過場效果,調整比例,多分辨率切換

支持切換播放器,進度條小窗口預覽

其他一些小動畫效果,rtsp、concat、mpeg

4.2 優缺點

ijkplayer 最大的優點就是可以根據需要編譯需要的解碼器。在編譯的時候通過 ln -s module-default.sh module.sh 選擇要編譯的解碼器。ijkplayer 在 config 目錄下提供了三種 module.sh 。也可自己修改 module.sh 。

ijkplayer 的缺點是庫太大。加入項目后會大大增加你的 APP 的大小。

11.3 關于我的個人博客和站點

github: https://github.com/yangchong211

知乎: https://www.zhihu.com/people/yang-chong-69-24/pins/posts

簡書: http://www.jianshu.com/u/b7b2c6ed9284

csdn: http://my.csdn.net/m0_37700275

喜馬拉雅聽書: http://www.ximalaya.com/zhubo/71989305/

泡在網上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1

郵箱:yangchong211@163.com

阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100239.headeruserinfo.3.dT4bcV

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/11064.html

相關文章

發表評論

0條評論

feng409

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<