主布局:

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="net.bwie.surfaceviewvideolist.MainActivity"> <android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"/> </RelativeLayout>

主布局的Item:

 <?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"> <TextView
android:id="@+id/progress_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="当前进度"/> <Button
android:id="@+id/play_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放"/> <TextView
android:id="@+id/title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题"/> <net.bwie.surfaceviewvideolist.widget.VideoSurfaceView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"/> </LinearLayout>

主界面Activity:

 /**
* 1、封装播放视频的SurfaceView
* 2、网络请求数据(手写bean):bean、httpservice
* 3、放在RecyclerView中展示
* 4、item中放入SurfaceView
* 5、点击播放弹出通知
* 6、进度
*/
public class MainActivity extends AppCompatActivity implements Callback<KaiyanBean> { protected RecyclerView mRecyclerView;
private Object mData; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_main);
initView(); initData();
} private void initData() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://baobab.kaiyanapp.com/")
.addConverterFactory(GsonConverterFactory.create()).build(); retrofit.create(KaiyanHttpService.class)
.getKaiyanCall()
.enqueue(this);
} private void initView() {
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
} @Override
public void onResponse(Call<KaiyanBean> call, Response<KaiyanBean> response) {
KaiyanBean kaiyanBean = response.body(); List<VideoBean> videoList = new ArrayList<>(); for (KaiyanBean.ItemBean itemBean : kaiyanBean.getItemList()) {
Log.d("1507","type: " + itemBean.getType()+ ", title : " + itemBean.getData().getTitle() + "url : " + itemBean.getData().getPlayUrl()); if ("video".equals(itemBean.getType())) {
// 过滤掉type不为video的数据
VideoBean videoBean = new VideoBean(itemBean.getData().getTitle(), itemBean.getData().getPlayUrl());
videoList.add(videoBean);
} } VideoListAdapter adapter = new VideoListAdapter(this, videoList);
mRecyclerView.setAdapter(adapter);
} @Override
public void onFailure(Call<KaiyanBean> call, Throwable t) { }
}

Bean:

 package net.bwie.surfaceviewvideolist.bean;

 import java.util.List;

 public class KaiyanBean {

     private List<ItemBean> itemList;

     public List<ItemBean> getItemList() {
return itemList;
} public void setItemList(List<ItemBean> itemList) {
this.itemList = itemList;
} public static class ItemBean {
public String getType() {
return type;
} public void setType(String type) {
this.type = type;
} private String type;
private DataBean data; public DataBean getData() {
return data;
} public void setData(DataBean data) {
this.data = data;
} public static class DataBean { private String title;
private String playUrl; public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public String getPlayUrl() {
return playUrl;
} public void setPlayUrl(String playUrl) {
this.playUrl = playUrl;
}
} } }
 package net.bwie.surfaceviewvideolist.bean;

 public class VideoBean {

     private String title;
private String playUrl; public VideoBean(String title, String playUrl) {
this.title = title;
this.playUrl = playUrl;
} public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public String getPlayUrl() {
return playUrl;
} public void setPlayUrl(String playUrl) {
this.playUrl = playUrl;
}
}

Http:

 package net.bwie.surfaceviewvideolist.httpservice;

 import net.bwie.surfaceviewvideolist.bean.KaiyanBean;

 import retrofit2.Call;
import retrofit2.http.GET; public interface KaiyanHttpService { @GET("api/v4/tabs/selected?udid=11111&vc=168&vn=3.3.1&deviceModel=Huawei%36&first_channel=eyepetizer_baidu_market&last_channel=eyepetizer_baidu_market&system_version_code=20")
Call<KaiyanBean> getKaiyanCall(); }

封装类:

 /**
* 能播放视频的SurfaceView,封装MediaPlayer
* 提供一个public方法用于设置播放路径和播放的方法
*/
public class VideoSurfaceView extends SurfaceView implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener {
private SurfaceHolder mHolder;
private MediaPlayer mMediaPlayer; public VideoSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs); init();
} private void init() {
// 获得缓冲区持有者
mHolder = getHolder();
// 设置生命周期的回调
mHolder.addCallback(this);
} // 设置播放路径并播放
public void playVideo(String path) {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
// 准备完毕监听器
mMediaPlayer.setOnPreparedListener(this);
} try {
// 重置MediaPlayer
mMediaPlayer.reset();
// 设置画面播放源
mMediaPlayer.setDisplay(mHolder);
// 设置播放源
mMediaPlayer.setDataSource(path);
// 准备播放
mMediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
Log.e("1507", e.getMessage());
} } // 停止播放
public void stop() {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
}
} @Override
public void surfaceCreated(SurfaceHolder holder) { } @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mMediaPlayer != null) {
mMediaPlayer.release();// 释放资源
mMediaPlayer = null;
}
} @Override
public void onPrepared(MediaPlayer mp) {
mMediaPlayer.start();
}
}

Adapter:

 public class VideoListAdapter extends RecyclerView.Adapter<VideoListAdapter.ViewHolder> {

     private Context mContext;
private List<VideoBean> mDatas; // 记录上一次播放的VideoView
private VideoSurfaceView mPlayingView; public VideoListAdapter(Context context, List<VideoBean> datas) {
mContext = context;
mDatas = datas;
} @Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mContext)
.inflate(R.layout.item_video, parent, false);
return new ViewHolder(itemView);
} @Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final VideoBean videoBean = mDatas.get(position); holder.mTitleTextView.setText(videoBean.getTitle()); // item刚复用进入屏幕时,无论是否播放都停止并隐藏
holder.mSurfaceView.stop();
holder.mSurfaceView.setVisibility(View.INVISIBLE); holder.mPlayBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { // 下一次播放时,停止上一次播放
if (mPlayingView != null) {
mPlayingView.stop();
mPlayingView.setVisibility(View.INVISIBLE);
} // 播放当前位置的视频
holder.mSurfaceView.setVisibility(View.VISIBLE);// 显示
holder.mSurfaceView.playVideo(videoBean.getPlayUrl()); mPlayingView = holder.mSurfaceView;
}
});
} @Override
public int getItemCount() {
return mDatas == null ? 0 : mDatas.size();
} static class ViewHolder extends RecyclerView.ViewHolder { Button mPlayBtn;
TextView mTitleTextView;
TextView mProgressTextView;
VideoSurfaceView mSurfaceView; public ViewHolder(View itemView) {
super(itemView); mPlayBtn = ((Button) itemView.findViewById(R.id.play_btn));
mTitleTextView = ((TextView) itemView.findViewById(R.id.title_tv));
mProgressTextView = ((TextView) itemView.findViewById(R.id.progress_tv));
mSurfaceView = ((VideoSurfaceView) itemView.findViewById(R.id.video_view));
}
} }

别忘了加权限:

<uses-permission android:name="android.permission.INTERNET"/>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

导包:

compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'

compile 'com.squareup.retrofit2:converter-gson:2.3.0'

compile 'com.squareup.okhttp3:okhttp:3.9.0'

compile 'com.github.bumptech.glide:glide:3.8.0'

SurfaceViewVideoList网络获取视频播放的更多相关文章

  1. Android热身:通过网络获取资源并更新UI组件

    Android热身:通过网络获取资源并更新UI组件 目标 点击"发送请求"按钮,下载某网页的html源码,并显示在TextView控件上:点击"清空",清除Te ...

  2. Android代码优化----PullToRefresh+universal-image-loader实现从网络获取数据并刷新

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  3. Android ListView从网络获取图片及文字显示

    上一篇文章说的是ListView展示本地的图片以及文本,这一篇说一下如何从网络获取图片以及文本来显示.事实上,一般是先获取Josn或sml数据,然后解释显示.我们先从网上获取xml,然后对其进行解析, ...

  4. 网络获取数据的Xml的Pull解析

    网络获取的XML的Pull解析 <?xml version="1.0" encoding="utf-8" ?> - <students> ...

  5. 网络获取的XML的Pull解析

    <?xml version="1.0" encoding="utf-8" ?> - <students> - <student x ...

  6. Android ListView 和 ***Adapter 从本地/网络获取歌曲列表

    本文内容 环境 项目结构 测试数据 演示 1:SimpleAdapter 演示 2:BaseAdapter 演示 3:CustomLazyList 演示 4:CustomLazyCompleteLis ...

  7. Android LazyList 从网络获取图片并缓存

    原演示地址 本文内容 环境 演示 LazyList 从网络获取图片并缓存 参考资料 本文是 Github 上的一个演示,通过网络获取歌手专辑的缩略图,并显示在 ListView 控件中.该演示具备将缩 ...

  8. Android Volley 库通过网络获取 JSON 数据

    本文内容 什么是 Volley 库 Volley 能做什么 Volley 架构 环境 演示 Volley 库通过网络获取 JSON 数据 参考资料 Android 关于网络操作一般都会介绍 HttpC ...

  9. Recorder︱深度学习小数据集表现、优化(Active Learning)、标注集网络获取

    一.深度学习在小数据集的表现 深度学习在小数据集情况下获得好效果,可以从两个角度去解决: 1.降低偏差,图像平移等操作 2.降低方差,dropout.随机梯度下降 先来看看深度学习在小数据集上表现的具 ...

随机推荐

  1. 坑爹的Sun JDK

    Sun的这个java.lang.Throwable 源码 设计非常糟糕,完全没有扩展性, 我在IBM 的Java JDK下,继承java.lang.Throwable重新定义了一个ExceptionW ...

  2. 再续session和cookie (网络整理)

    摘要:虽然session机制在web应用程序中被采用已经很长时间了,但是仍然有很多人不清楚session机制的本质,以至不能正确的应用这一技术.本文将详细讨论session的工作机制并且对在Java ...

  3. FactoryMethod工厂方法模式升级成AbstractFactory抽象工厂模式

    具体参考抽象工厂(AbstractFactory)模式-创建型模式,本文在FactoryMethod工厂方法模式(创建型模式)的基础上进行业务进一步抽象,不做详细原理介绍. 1.在FactoryMet ...

  4. php -- 文件上传下载

    ----- 026-upload.php ----- <!DOCTYPE html> <html> <head> <meta http-equiv=" ...

  5. [原创]Entity Framework查询原理

    前言 Entity Framework的全称是ADO.NET Entity Framework,是微软开发的基于ADO.NET的ORM(Object/Relational Mapping)框架.Ent ...

  6. Python学习--18 进程和线程

    线程是最小的执行单元,而进程由至少一个线程组成.如何调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间. 进程 fork调用 通过fork()系统调用,就可以生成一个子进程 ...

  7. 了解Spring-boot-starter常用依赖模块

    Spring-boot的优点: 1.Spring框架的“约定优先于配置(COC)”理念以及最佳实践. 2.针对日常企业应用研发各种场景的Spring-boot-starter自动配置依赖模块,且“开箱 ...

  8. Java NIO系列教程(六) Selector

    Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管理多个网络连接. 下面是 ...

  9. JVM学习记录-类加载器

    前言 JVM设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外面去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为“类 ...

  10. http server 简单实现

    本blog主要是模仿http server的实现,使得客户端使用浏览器访问server所指定的目录. 当访问的为一个目录时, 则列出改目录下的所有文件 当访问的是文件时,则下载文件到本地 本log仅仅 ...