最近在我的个人项目中集成了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添加:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 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)布局:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?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源码中进行修改,添加以下代码:

1
2
3
4
5
6
7
8
9
   public IRenderView getmRenderView() {
        return mRenderView;
    }
    public int getmVideoWidth() {
        return mVideoWidth;
    }
    public int getmVideoHeight() {
        return mVideoHeight;
    }

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//横竖屏检测切换
    @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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
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销毁时取消后台播放:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    @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所有源码:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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);
        }
    }
}