Android 开发经验集Android开发经验谈Android开发

bilibili开源库ijkPalyer的集成和使用

2017-12-08  本文已影响106人  smartzheng

最近在我的个人项目中集成了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);
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读