bilibili开源库ijkPalyer的集成和使用

作者: smartzheng | 来源:发表于2017-12-08 18:23 被阅读106次

    最近在我的个人项目中集成了bilibili视频播放库ijkPalyer,网上的很多教程所写的是之前版本的使用方法,官方文档也没有写的太清楚,所以在此做一个简单的介绍。
    个人项目:一个基于MVP,dagger2,RXJava,Retrofit,Glide,集成bilibili的ijkPlayer,用Bmob实现后台服务,遵循Material Design风格的APP,数据主要来自豆瓣。欢迎star。
    地址:https://github.com/smartzheng/LoveDouBan

    1.引入
    之前的版本似乎需要进行源码编译,现在直接引入即可。ijkPalyer地址:https://github.com/Bilibili/ijkplayer
    最简单的方式,直接在app下的gradle添加:

    # required
    allprojects {
        repositories {
            jcenter()
        }
    }
    
    dependencies {
        # required, enough for most devices.
        compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
        compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
    
        # Other ABIs: optional
        compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.4'
        compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.4'
        compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.4'
        compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.4'
    
        # ExoPlayer as IMediaPlayer: optional, experimental
        compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.4'
    }
    

    如果对源码有兴趣,可以将项目下的以下指出的文件夹(ijkplayer-example可根据需求进行选择,下面会进行介绍)引入到app中:



    其中tools直接拷贝,其他文件夹以module的形式引入,再添加为项目依赖即可。

    ijkPlayer的定制性比较强,在官方地址下有一个sample,可以将其直接以项目的形式引入至自己的项目中进行使用,其中包括了不少官方写好的工具类和控件。
    当然,为了减小apk大小,直接引入一个项目不是好选择,所以我选择复制粘贴需要的代码,如下:



    上图中的wiget目录可全部拷贝入自己的项目中,拷贝完成之后会缺少很多资源文件。所以需要再根据报错信息分别将res目录下的相关资源和声明复制到对应的目录或文件中:



    layout直接拷贝,values复制内容至自己项目对应的values文件中去,并注意删除重复和未使用的声明。

    至此,引入完毕。
    2.简单使用
    1)初始化:官方提供以下两种方式进行初始化操作,在应用初始化或者使用视频播放的activity初始化时调用以下方法。

        //第一:默认初始化
        Bmob.initialize(this, "e8f177acd86e0fde391b2af19243fc1b");
        // 注:自v3.5.2开始,数据sdk内部缝合了统计sdk,开发者无需额外集成,传渠道参数即可,不传默认没开启数据统计功能
        //Bmob.initialize(this, "Your Application ID","bmob");
    
        //第二:自v3.4.7版本开始,设置BmobConfig,允许设置请求超时时间、文件分片上传时每片的大小、文件的过期时间(单位为秒),
        //BmobConfig config =new BmobConfig.Builder(this)
        ////设置appkey
        //.setApplicationId("Your Application ID")
        ////请求超时时间(单位为秒):默认15s
        //.setConnectTimeout(30)
        ////文件分片上传时每片的大小(单位字节),默认512*1024
        //.setUploadBlockSize(1024*1024)
        ////文件的过期时间(单位为秒):默认1800s
        //.setFileExpiration(2500)
        //.build();
        //Bmob.initialize(config);
    

    2)布局:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <!-- The main content view -->
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorPrimary">
    
            <com.zs.douban.customview.media.IjkVideoView
                android:id="@+id/video_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center">
    
            </com.zs.douban.customview.media.IjkVideoView>
    
            <TextView
                android:id="@+id/toast_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="left|center_vertical"
                android:background="@color/colorPrimary"
                android:padding="16dp"
                android:textSize="16sp"
                android:visibility="gone"/>
    
            <TableLayout
                android:visibility="invisible"
                android:id="@+id/hud_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right|center_vertical"
                android:background="@color/colorPrimary"
                android:padding="8dp"/>
    
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:minHeight="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
        </FrameLayout>
    
        <!-- The navigation drawer -->
        <FrameLayout
            android:id="@+id/right_drawer"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="right"
            android:background="@color/colorPrimary"/>
    </android.support.v4.widget.DrawerLayout>
    

    以上是我项目下的布局内容,可以根据需求自定义,但是需要引入com.zs.douban.customview.media.IjkVideoView,以及一个TableLayout,播放视频时TableLayout会显示对应的播放信息,如果不需要,可以设为invisible,但是如果不加入,会报错,可能需要修改源码才能避免。

    3)配置和播放

    private void initPlayer() {
        IjkMediaPlayer.loadLibrariesOnce(null);
        IjkMediaPlayer.native_profileBegin("libijkplayer.so");
        mVideoView = (IjkVideoView) findViewById(R.id.video_view);
        mVideoView.setHudView(mHudView);//没有TableLayout此处会报空指针
        AndroidMediaController controller = new AndroidMediaController(this, false);
        mVideoView.setMediaController(controller);
    }
    
    private void play() {
        String url = getIntent().getStringExtra("url");//设置播放地址
        mVideoView.setVideoURI(Uri.parse(url));
        mVideoView.start();
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
    

    4)全屏
    默认情况下,播放为竖屏小窗口。全屏需要在IjkViewView源码中进行修改,添加以下代码:

       public IRenderView getmRenderView() {
            return mRenderView;
        }
        public int getmVideoWidth() {
            return mVideoWidth;
        }
        public int getmVideoHeight() {
            return mVideoHeight;
        }
    

    在播放视频的activity中增加以下方法(具体可以查看我的项目下的MoviePlayActivity):

    //横竖屏检测切换
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            //重新获取屏幕宽高
            initScreenInfo();
            if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {//切换为横屏
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mVideoView.getLayoutParams();
                lp.height = screenHeight;
                lp.width = screenWidth;
                mVideoView.setLayoutParams(lp);
            } else {
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mVideoView.getLayoutParams();
                lp.height = screenWidth * 9 / 16;
                lp.width = screenWidth;
                mVideoView.setLayoutParams(lp);
            }
            setScreenRate(currentSize);
        }
        //初始化屏幕配置信息
        private void initScreenInfo() {
            WindowManager wm = this.getWindowManager();
            screenWidth = wm.getDefaultDisplay().getWidth();
            screenHeight = wm.getDefaultDisplay().getHeight();
        }
    
        //设置视频播放比例
        public void setScreenRate(int rate) {
            int width = 0;
            int height = 0;
            if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {// 横屏
                if (rate == SIZE_DEFAULT) {
                    width = mVideoView.getmVideoWidth();
                    height = mVideoView.getmVideoHeight();
                } else if (rate == SIZE_4_3) {
                    width = screenHeight / 3 * 4;
                    height = screenHeight;
                } else if (rate == SIZE_16_9) {
                    width = screenHeight / 9 * 16;
                    height = screenHeight;
                }
            } else { //竖屏
                if (rate == SIZE_DEFAULT) {
                    width = mVideoView.getmVideoWidth();
                    height = mVideoView.getmVideoHeight();
                } else if (rate == SIZE_4_3) {
                    width = screenWidth;
                    height = screenWidth * 3 / 4;
                } else if (rate == SIZE_16_9) {
                    width = screenWidth;
                    height = screenWidth * 9 / 16;
                }
            }
            if (width > 0 && height > 0) {
                FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mVideoView.getmRenderView().getView().getLayoutParams();
                lp.width = width;
                lp.height = height;
                mVideoView.getmRenderView().getView().setLayoutParams(lp);
            }
        }
    
        //手动切换
        private void fullChangeScreen() {
            if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {// 切换为竖屏
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
        }
    

    播放时调用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)即可。

    5)播放进度,需自行加入SeekBar:

    seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        ....
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
             video.seekTo(seekBar.getProgress()*video.getDuration()/100);
             ...
        }
    });
    //视频开始播放时使用handle.sendMessageDelayed更新时间显示
    private void refreshTime(){
        int totalSeconds = video.getCurrentPosition() / 1000;
        int seconds = totalSeconds % 60;
        int minutes = (totalSeconds / 60) % 60;
        int hours = totalSeconds / 3600;
        String ti=hours > 0 ? String.format("%02d:%02d:%02d", hours, minutes, seconds):String.format("%02d:%02d", minutes, seconds);
        time.setText(ti);
    }
    

    4、最后,需要根据需求在返回键或者activity销毁时取消后台播放:

        @Override
        public void onBackPressed() {
            mBackPressed = true;
    
            super.onBackPressed();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
    
            if (mBackPressed || !mVideoView.isBackgroundPlayEnabled()) {
                mVideoView.stopPlayback();
                mVideoView.release(true);
                mVideoView.stopBackgroundPlay();
            } else {
                mVideoView.enterBackground();
            }
            IjkMediaPlayer.native_profileEnd();
        }
    

    补充Activity所有源码:

    public class MoviePlayActivity extends AppCompatActivity {
        @InjectView(R.id.video_view)
        IjkVideoView mVideoView;
        @InjectView(R.id.toast_text_view)
        TextView mToastTextView;
        @InjectView(R.id.hud_view)
        TableLayout mHudView;
        @InjectView(R.id.toolbar)
        Toolbar mToolbar;
        @InjectView(R.id.right_drawer)
        FrameLayout mRightDrawer;
        @InjectView(R.id.drawer_layout)
        DrawerLayout mDrawerLayout;
        private boolean mBackPressed;
        private static final int SIZE_DEFAULT = 0;
        private static final int SIZE_4_3 = 1;
        private static final int SIZE_16_9 = 2;
        private int currentSize = SIZE_16_9;
        private int screenHeight;
        private int screenWidth;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_movie_play);
            ButterKnife.inject(this);
            initToolBar();
            initPlayer();
            play();
        }
    
        /**
         * 初始化ToolBar
         */
        private void initToolBar() {
            mToolbar.setTitleTextColor(Color.WHITE);
            setSupportActionBar(mToolbar);
            final ActionBar actionBar = getSupportActionBar();
            if (actionBar != null) {
    //            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
                actionBar.setDisplayHomeAsUpEnabled(true);
                actionBar.setTitle(getIntent().getStringExtra("title"));
            }
        }
    
        //
        private void initPlayer() {
            IjkMediaPlayer.loadLibrariesOnce(null);
            IjkMediaPlayer.native_profileBegin("libijkplayer.so");
            mVideoView = (IjkVideoView) findViewById(R.id.video_view);
            mVideoView.setHudView(mHudView);
            AndroidMediaController controller = new AndroidMediaController(this, false);
            mVideoView.setMediaController(controller);
        }
    
        private void play() {
            String url = getIntent().getStringExtra("url");
            mVideoView.setVideoURI(Uri.parse(url));
            mVideoView.start();
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
    
        @Override
        public void onBackPressed() {
            mBackPressed = true;
    
            super.onBackPressed();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
    
            if (mBackPressed || !mVideoView.isBackgroundPlayEnabled()) {
                mVideoView.stopPlayback();
                mVideoView.release(true);
                mVideoView.stopBackgroundPlay();
            } else {
                mVideoView.enterBackground();
            }
            IjkMediaPlayer.native_profileEnd();
        }
    
        //横竖屏检测切换
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            //重新获取屏幕宽高
            initScreenInfo();
            if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {//切换为横屏
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mVideoView.getLayoutParams();
                lp.height = screenHeight;
                lp.width = screenWidth;
                mVideoView.setLayoutParams(lp);
            } else {
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mVideoView.getLayoutParams();
                lp.height = screenWidth * 9 / 16;
                lp.width = screenWidth;
                mVideoView.setLayoutParams(lp);
            }
            setScreenRate(currentSize);
        }
        //初始化屏幕配置信息
        private void initScreenInfo() {
            WindowManager wm = this.getWindowManager();
            screenWidth = wm.getDefaultDisplay().getWidth();
            screenHeight = wm.getDefaultDisplay().getHeight();
        }
    
        //设置视频播放比例
        public void setScreenRate(int rate) {
            int width = 0;
            int height = 0;
            if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {// 横屏
                if (rate == SIZE_DEFAULT) {
                    width = mVideoView.getmVideoWidth();
                    height = mVideoView.getmVideoHeight();
                } else if (rate == SIZE_4_3) {
                    width = screenHeight / 3 * 4;
                    height = screenHeight;
                } else if (rate == SIZE_16_9) {
                    width = screenHeight / 9 * 16;
                    height = screenHeight;
                }
            } else { //竖屏
                if (rate == SIZE_DEFAULT) {
                    width = mVideoView.getmVideoWidth();
                    height = mVideoView.getmVideoHeight();
                } else if (rate == SIZE_4_3) {
                    width = screenWidth;
                    height = screenWidth * 3 / 4;
                } else if (rate == SIZE_16_9) {
                    width = screenWidth;
                    height = screenWidth * 9 / 16;
                }
            }
            if (width > 0 && height > 0) {
                FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mVideoView.getmRenderView().getView().getLayoutParams();
                lp.width = width;
                lp.height = height;
                mVideoView.getmRenderView().getView().setLayoutParams(lp);
            }
        }
    
        //手动切换
        private void fullChangeScreen() {
            if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {// 切换为竖屏
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:bilibili开源库ijkPalyer的集成和使用

        本文链接:https://www.haomeiwen.com/subject/eeosixtx.html