前段时间由于项目需要用到类似于今日头条的视频播放器,实现在线播放,边缓存边播放,当然也可以播放本地文件,如下图:

这里我推荐大家使用的是jiecaovideoplayer开源库,这个库的播放引擎是ijkplayer,它调用ffmpeg, 原项目GitHub地址:https://github.com/lipangit/JieCaoVideoPlayer
一、项目引入:
1、添加类库
1 2 | compile 'fm.jiecao:jiecaovideoplayer:4.8.3'compile 'com.github.bumptech.glide:glide:3.7.0' |
2、添加布局
1 | <fm.jiecao.jcvideoplayer_lib.jcvideoplayerstandard android:id= "@+id/player_list_video" android:layout_width= "match_parent" android:layout_height= "220dp" ></fm.jiecao.jcvideoplayer_lib.jcvideoplayerstandard> |
3、下面就是我所说的通过设置视频地址、缩略图地址、标题等几行代码快速实现视频的播放啦
1 2 3 4 5 | JCVideoPlayerStandard player = (JCVideoPlayerStandard) findViewById(R.id.player_list_video); boolean setUp = player.setUp( "https://gslb.miaopai.com/stream/ed5HCfnhovu3tyIQAiv60Q__.mp4" , JCVideoPlayer.SCREEN_LAYOUT_LIST, "" ); if (setUp) { Glide.with(MainActivity. this ).load( "https://a4.att.hudong.com/05/71/01300000057455120185716259013.jpg" ).into(player.thumbImageView); } |
4、在Activity中
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Override public void onBackPressed() { if (JCVideoPlayer.backPress()) { return ; } super .onBackPressed(); } @Override protected void onPause() { super .onPause(); JCVideoPlayer.releaseAllVideos(); } |
5、还有一点不要忘记哦,要添加权限滴:
1 2 | <!--联网权限--> <uses-permission android:name= "android.permission.INTERNET" ></uses-permission> |
下面我们来看看我们运行效果:

二、如何使用jiecaovideoplayer播放本地视频
注意:jiecaovideoplayer支持file:///开头的文件播放,但是不支持assets或者raw目录下的视频,assets下的视频要先复制到本地路径才能播放,至于怎么监听播放完全呢,要继承JCvideoPlayerStandard 复写onAutoCOmplete函数
三、模拟用户点击开始按钮,直接进入全屏
1 2 3 4 | //直接进入全屏 player.startFullscreen( this , JCVideoPlayerStandard. class , videoUrl, "" ); //模拟用户点击开始按钮,NORMAL状态下点击开始播放视频,播放中点击暂停视频 player.startButton.performClick(); |
我把代码都贴出来吧:
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 | package la.trytry.jiecaovideoplayer; import android.os.Bundle;import android.support.v7.app.AppCompatActivity; import com.bumptech.glide.Glide; import fm.jiecao.jcvideoplayer_lib.JCVideoPlayer;import fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard; public class MainActivity extends AppCompatActivity { private JCVideoPlayerStandard player; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); player = (JCVideoPlayerStandard) findViewById(R.id.player_list_video); boolean setUp = player.setUp(videoUrl, JCVideoPlayer.SCREEN_LAYOUT_LIST, "" ); if (setUp) { Glide.with(MainActivity. this ).load( "https://a4.att.hudong.com/05/71/01300000057455120185716259013.jpg" ).into(player.thumbImageView); } //直接进入全屏 player.startFullscreen( this , JCVideoPlayerStandard. class , videoUrl, "" ); //模拟用户点击开始按钮,NORMAL状态下点击开始播放视频,播放中点击暂停视频 player.startButton.performClick(); } @Override public void onBackPressed() { if (JCVideoPlayer.backPress()) { return ; } super .onBackPressed(); } @Override protected void onPause() { super .onPause(); JCVideoPlayer.releaseAllVideos(); } }<ul class = "pre-numbering" ><img src= "/uploadfile/Collfiles/20170721/20170721093008222.png" style= "width: 105px; height: 60px;" ><ul class = "pre-numbering" ></ul></ul> |
四、下面回到我们的主题上,实现仿今日头条的视频播放
1、VideoActivity.Java
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 | package la.trytry.jiecaovideoplayer; import android.graphics.Rect;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.widget.AbsListView;import android.widget.ListView; import java.util.ArrayList; import fm.jiecao.jcvideoplayer_lib.JCVideoPlayer;import fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard; public class VideoActivity extends AppCompatActivity { private ListView listView; private ArrayList<string> datas; private JCVideoPlayerStandard currPlayer; private VideoAdapter adapter; private AbsListView.OnScrollListener onScrollListener; private int firstVisible; //当前第一个可见的item private int visibleCount; //当前可见的item个数 @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_video); listView = (ListView) findViewById(R.id.listview); initDatas(); initListener(); } private void initDatas() { datas = new ArrayList<string>(); for ( int i = 0 ; i < 20 ; i++) { datas.add(videoUrl); } adapter = new VideoAdapter(VideoActivity. this , datas, R.layout.item_video); listView.setAdapter(adapter); } /** * 滑动监听 */ private void initListener() { onScrollListener = new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case AbsListView.OnScrollListener.SCROLL_STATE_FLING: break ; case AbsListView.OnScrollListener.SCROLL_STATE_IDLE: //滑动停止自动播放视频 autoPlayVideo(view); break ; case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: break ; } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (firstVisible == firstVisibleItem) { return ; } firstVisible = firstVisibleItem; visibleCount = visibleItemCount; } }; listView.setOnScrollListener(onScrollListener); } /** * 滑动停止自动播放视频 */ private void autoPlayVideo(AbsListView view) { for ( int i = 0 ; i < visibleCount; i++) { if (view != null && view.getChildAt(i) != null && view.getChildAt(i).findViewById(R.id.player_list_video) != null ) { currPlayer = (JCVideoPlayerStandard) view.getChildAt(i).findViewById(R.id.player_list_video); Rect rect = new Rect(); //获取当前view 的 位置 currPlayer.getLocalVisibleRect(rect); int videoheight = currPlayer.getHeight(); if (rect.top == 0 && rect.bottom == videoheight) { if (currPlayer.currentState == JCVideoPlayer.CURRENT_STATE_NORMAL || currPlayer.currentState == JCVideoPlayer.CURRENT_STATE_ERROR) { currPlayer.startButton.performClick(); } return ; } } } //释放其他视频资源 JCVideoPlayer.releaseAllVideos(); } @Override public void onBackPressed() { if (JCVideoPlayer.backPress()) { return ; } super .onBackPressed(); } @Override protected void onPause() { super .onPause(); JCVideoPlayer.releaseAllVideos(); }}<img src= "/uploadfile/Collfiles/20170721/20170721093008222.png" style= "width: 105px; height: 60px;" ></string></string> |
在我们滑动的时候,jiecaovideoplayer会自动停止正在播放的视频,这里面我还添加了一个功能,就是监听当滑动停止的时候自动播放下一个视频
2、VideoAdapter.java
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 | package la.trytry.jiecaovideoplayer; import android.content.Context; import com.bumptech.glide.Glide;import com.zhy.adapter.abslistview.CommonAdapter;import com.zhy.adapter.abslistview.ViewHolder; import java.util.List; import fm.jiecao.jcvideoplayer_lib.JCVideoPlayer;import fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard; /** * @author: lijuan * @description: 适配器 * @date: 2016-12-04 * @time: 17:04 */public class VideoAdapter extends CommonAdapter<string> { private Context mContext; public VideoAdapter(Context context, List<string> datas, int layoutId) { super (context, layoutId, datas); this .mContext = context; } @Override protected void convert(ViewHolder viewHolder, String url, int position) { JCVideoPlayerStandard player = viewHolder.getView(R.id.player_list_video); if (player != null ) { player.release(); } boolean setUp = player.setUp(url, JCVideoPlayer.SCREEN_LAYOUT_LIST, "" ); if (setUp) { Glide.with(mContext).load( "https://a4.att.hudong.com/05/71/01300000057455120185716259013.jpg" ).into(player.thumbImageView); } }}<img src= "/uploadfile/Collfiles/20170721/20170721093008222.png" style= "width: 105px; height: 60px;" ></string></string> |
这里的适配器,我继承了鸿洋大神写的万能的Adapter,所以我们还需添加这个库的引用
1 | compile 'com.zhy:base-adapter:3.0.3' <ul class = "pre-numbering" > 1 <img src= "/uploadfile/Collfiles/20170721/20170721093008222.png" style= "width: 105px; height: 60px;" ><ul class = "pre-numbering" > 1 </ul></ul> |
3、item_video.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!--?xml version= "1.0" encoding= "utf-8" ?--><linearlayout xmlns:android= "https://schemas.android.com/apk/res/android" android:layout_width= "match_parent" android:layout_height= "wrap_content" android:orientation= "vertical" > <fm.jiecao.jcvideoplayer_lib.jcvideoplayerstandard android:id= "@+id/player_list_video" android:layout_width= "match_parent" android:layout_height= "190dp" > <relativelayout android:layout_width= "match_parent" android:layout_height= "wrap_content" android:paddingbottom= "8dp" android:paddingtop= "8dp" > <imageview android:id= "@+id/img_video_icon" android:layout_width= "30dp" android:layout_height= "30dp" android:layout_marginleft= "12dp" android:src= "@mipmap/icon_default_head" > <textview android:id= "@+id/tv_video_userName" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_centervertical= "true" android:layout_marginleft= "12dp" android:layout_torightof= "@id/img_video_icon" android:text= "空城旧梦" > <textview android:id= "@+id/tv_video_comment" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_alignparentright= "true" android:layout_centervertical= "true" android:layout_marginright= "12dp" android:drawablepadding= "4dp" android:drawableleft= "@mipmap/icon_comment" android:text= "21" android:textsize= "12sp" > <textview android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_centervertical= "true" android:layout_marginright= "12dp" android:layout_toleftof= "@id/tv_video_comment" android:text= "3万次播放" > </textview></textview></textview></imageview></relativelayout></fm.jiecao.jcvideoplayer_lib.jcvideoplayerstandard></linearlayout><img src= "/uploadfile/Collfiles/20170721/20170721093008222.png" style= "width: 105px; height: 60px;" > |
4、activity_video.xml
1 2 | <!--?xml version= "1.0" encoding= "utf-8" ?--><listview xmlns:android= "https://schemas.android.com/apk/res/android" android:id= "@+id/listview" android:layout_width= "match_parent" android:layout_height= "match_parent" android:orientation= "vertical" ><ul class = "pre-numbering" > 123456 <img src= "/uploadfile/Collfiles/20170721/20170721093008222.png" style= "width: 105px; height: 60px;" ><ul class = "pre-numbering" > 123456 </ul></ul></listview> |
下面我们看看最终的效果

好了,本篇文章已经全部写完但是当在fragment中加载视屏时无法全屏播放,不知道为啥