前段时间由于项目需要用到类似于今日头条的视频播放器,实现在线播放,边缓存边播放,当然也可以播放本地文件,如下图:
这里我推荐大家使用的是jiecaovideoplayer开源库,这个库的播放引擎是ijkplayer,它调用ffmpeg, 原项目GitHub地址:https://github.com/lipangit/JieCaoVideoPlayer
一、项目引入:
1、添加类库
compile 'fm.jiecao:jiecaovideoplayer:4.8.3'
compile 'com.github.bumptech.glide:glide:3.7.0'
2、添加布局
<fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard
android:id="@+id/player_list_video"
android:layout_width="match_parent"
android:layout_height="220dp" />
3、下面就是我所说的通过设置视频地址、缩略图地址、标题等几行代码快速实现视频的播放啦
JCVideoPlayerStandard player = (JCVideoPlayerStandard) findViewById(R.id.player_list_video);
boolean setUp = player.setUp("http://gslb.miaopai.com/stream/ed5HCfnhovu3tyIQAiv60Q__.mp4", JCVideoPlayer.SCREEN_LAYOUT_LIST, "");
if (setUp) {
Glide.with(MainActivity.this).load("http://a4.att.hudong.com/05/71/01300000057455120185716259013.jpg").into(player.thumbImageView);
}
4、在Activity中
@Override
public void onBackPressed() {
if (JCVideoPlayer.backPress()) {
return;
}
super.onBackPressed();
}
@Override
protected void onPause() {
super.onPause();
JCVideoPlayer.releaseAllVideos();
}
5、还有一点不要忘记哦,要添加权限滴:
<!--联网权限-->
<uses-permission android:name="android.permission.INTERNET" />
下面我们来看看我们运行效果:
这里写图片描述
二、如何使用jiecaovideoplayer播放本地视频
注意:jiecaovideoplayer支持file:///开头的文件播放,但是不支持assets或者raw目录下的视频,assets下的视频要先复制到本地路径才能播放,至于怎么监听播放完全呢,要继承JCvideoPlayerStandard 复写onAutoCOmplete函数
三、模拟用户点击开始按钮,直接进入全屏
//直接进入全屏
player.startFullscreen(this, JCVideoPlayerStandard.class, videoUrl, "");
//模拟用户点击开始按钮,NORMAL状态下点击开始播放视频,播放中点击暂停视频
player.startButton.performClick();
我把代码都贴出来吧:
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 String videoUrl = "http://gslb.miaopai.com/stream/ed5HCfnhovu3tyIQAiv60Q__.mp4";
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("http://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();
}
}
四、下面回到我们的主题上,实现仿今日头条的视频播放
1、VideoActivity.java
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 String videoUrl = "http://gslb.miaopai.com/stream/ed5HCfnhovu3tyIQAiv60Q__.mp4";
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();
}
}
在我们滑动的时候,jiecaovideoplayer会自动停止正在播放的视频,这里面我还添加了一个功能,就是监听当滑动停止的时候自动播放下一个视频
2、VideoAdapter.java
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("http://a4.att.hudong.com/05/71/01300000057455120185716259013.jpg").into(player.thumbImageView);
}
}
}
这里的适配器,我继承了鸿洋大神写的万能的Adapter,所以我们还需添加这个库的引用
compile 'com.zhy:base-adapter:3.0.3'
3、item_video.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://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万次播放" />
</RelativeLayout>
</LinearLayout>
4、activity_video.xml
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
下面我们看看最终的效果
好了,本篇文章已经全部写完了,存在总结不到位的地方还望指导,感谢_
网友评论
怎么出现这种错误
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//点击物理返回键时 判断视频是否全屏播放 是的话销毁全屏
if (JZVideoPlayer.backPress()) {
return true;
}
}
return super.onKeyDown(keyCode, event);
}
09-19 18:07:41.216 24181-24529/com.example.aa.videoapp E/IJKMEDIA: https://app.tongyejianghubang.com/UploadImages/201709/19/201709191731133120ru7RU2.mp4: Protocol not found
09-19 18:07:41.226 24181-24296/com.example.aa.videoapp E/tv.danmaku.ijk.media.player.IjkMediaPlayer: Error (-10000,0)
09-19 18:07:41.266 24181-24181/com.example.aa.videoapp E/JieCaoVideoPlayer: onError -10000 - 0 [1124619048]
09-19 18:09:40.704 24181-24181/com.example.aa.videoapp E/Parcel: Reading a NULL string not supported here.
急啊!
java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/com.example.ken.testmedioplay-1/lib/x86/libijkffmpeg.so: has text relocations
-keep class fm.jiecao.** {*;}
-dontwarn tv.danmaku.**
-keep class tv.danmaku.** {*;}
怎么解决啊?
因为这个需要父类继承AppCompatActivity 而不能是Activity,报错是因为Activity中没有actionbar。如果项目暂时不能继承AppCompatActivity,上面地址会给出解决方案
05-09 16:49:58.496 17511-17511/fm.jiecao.jiecaovideoplayer E/AndroidRuntime: in writeCrashedAppName, pkgName :fm.jiecao.jiecaovideoplayer
05-09 16:49:58.496 17511-17511/fm.jiecao.jiecaovideoplayer D/AndroidRuntime: file written successfully with content: fm.jiecao.jiecaovideoplayer StringBuffer : ;fm.jiecao.jiecaovideoplayer
05-09 16:49:58.496 17511-17511/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: fm.jiecao.jiecaovideoplayer, PID: 17511
java.lang.NullPointerException
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayer.showSupportActionBar(JCVideoPlayer.java:878)
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayer.clearFullscreenLayout(JCVideoPlayer.java:446)
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayer.onCompletion(JCVideoPlayer.java:482)
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayerManager.completeAll(JCVideoPlayerManager.java:42)
at fm.jiecao.jcvideoplayer_lib.JCVideoPlayer.prepareMediaPlayer(JCVideoPlayer.java:199)
at
http://blog.csdn.net/First_CooMan/article/details/69367519
因为这个需要父类继承AppCompatActivity 而不能是Activity,报错是因为Activity中没有actionbar。如果项目暂时不能继承AppCompatActivity,上面地址会给出解决方案
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait"></activity>
明白了吗?
public void onBackPressed() {
if (JCVideoPlayer.backPress()) {
return;
}
super.onBackPressed();
}
JCVideoPlayer.backPress() 有这个方法吗?报错耶
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//点击物理返回键时 判断视频是否全屏播放 是的话销毁全屏
if (JZVideoPlayer.backPress()) {
return true;
}
}
return super.onKeyDown(keyCode, event);
}