主布局:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. xmlns:app="http://schemas.android.com/apk/res-auto"
  5. xmlns:tools="http://schemas.android.com/tools"
  6. android:layout_width="match_parent"
  7. android:layout_height="match_parent"
  8. tools:context="net.bwie.surfaceviewvideolist.MainActivity">
  9.  
  10. <android.support.v7.widget.RecyclerView
  11. android:id="@+id/recycler_view"
  12. android:layout_width="match_parent"
  13. android:layout_height="match_parent"
  14. app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
  15.  
  16. </RelativeLayout>

主布局的Item:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:orientation="vertical">
  6.  
  7. <TextView
  8. android:id="@+id/progress_tv"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:text="当前进度"/>
  12.  
  13. <Button
  14. android:id="@+id/play_btn"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:text="播放"/>
  18.  
  19. <TextView
  20. android:id="@+id/title_tv"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:text="标题"/>
  24.  
  25. <net.bwie.surfaceviewvideolist.widget.VideoSurfaceView
  26. android:id="@+id/video_view"
  27. android:layout_width="match_parent"
  28. android:layout_height="200dp"
  29. android:layout_gravity="center_horizontal"/>
  30.  
  31. </LinearLayout>

主界面Activity:

  1. /**
  2. * 1、封装播放视频的SurfaceView
  3. * 2、网络请求数据(手写bean):bean、httpservice
  4. * 3、放在RecyclerView中展示
  5. * 4、item中放入SurfaceView
  6. * 5、点击播放弹出通知
  7. * 6、进度
  8. */
  9. public class MainActivity extends AppCompatActivity implements Callback<KaiyanBean> {
  10.  
  11. protected RecyclerView mRecyclerView;
  12. private Object mData;
  13.  
  14. @Override
  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. super.setContentView(R.layout.activity_main);
  18. initView();
  19.  
  20. initData();
  21. }
  22.  
  23. private void initData() {
  24. Retrofit retrofit = new Retrofit.Builder()
  25. .baseUrl("http://baobab.kaiyanapp.com/")
  26. .addConverterFactory(GsonConverterFactory.create()).build();
  27.  
  28. retrofit.create(KaiyanHttpService.class)
  29. .getKaiyanCall()
  30. .enqueue(this);
  31. }
  32.  
  33. private void initView() {
  34. mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
  35. }
  36.  
  37. @Override
  38. public void onResponse(Call<KaiyanBean> call, Response<KaiyanBean> response) {
  39. KaiyanBean kaiyanBean = response.body();
  40.  
  41. List<VideoBean> videoList = new ArrayList<>();
  42.  
  43. for (KaiyanBean.ItemBean itemBean : kaiyanBean.getItemList()) {
  44. Log.d("1507","type: " + itemBean.getType()+ ", title : " + itemBean.getData().getTitle() + "url : " + itemBean.getData().getPlayUrl());
  45.  
  46. if ("video".equals(itemBean.getType())) {
  47. // 过滤掉type不为video的数据
  48. VideoBean videoBean = new VideoBean(itemBean.getData().getTitle(), itemBean.getData().getPlayUrl());
  49. videoList.add(videoBean);
  50. }
  51.  
  52. }
  53.  
  54. VideoListAdapter adapter = new VideoListAdapter(this, videoList);
  55. mRecyclerView.setAdapter(adapter);
  56. }
  57.  
  58. @Override
  59. public void onFailure(Call<KaiyanBean> call, Throwable t) {
  60.  
  61. }
  62. }

Bean:

  1. package net.bwie.surfaceviewvideolist.bean;
  2.  
  3. import java.util.List;
  4.  
  5. public class KaiyanBean {
  6.  
  7. private List<ItemBean> itemList;
  8.  
  9. public List<ItemBean> getItemList() {
  10. return itemList;
  11. }
  12.  
  13. public void setItemList(List<ItemBean> itemList) {
  14. this.itemList = itemList;
  15. }
  16.  
  17. public static class ItemBean {
  18. public String getType() {
  19. return type;
  20. }
  21.  
  22. public void setType(String type) {
  23. this.type = type;
  24. }
  25.  
  26. private String type;
  27. private DataBean data;
  28.  
  29. public DataBean getData() {
  30. return data;
  31. }
  32.  
  33. public void setData(DataBean data) {
  34. this.data = data;
  35. }
  36.  
  37. public static class DataBean {
  38.  
  39. private String title;
  40. private String playUrl;
  41.  
  42. public String getTitle() {
  43. return title;
  44. }
  45.  
  46. public void setTitle(String title) {
  47. this.title = title;
  48. }
  49.  
  50. public String getPlayUrl() {
  51. return playUrl;
  52. }
  53.  
  54. public void setPlayUrl(String playUrl) {
  55. this.playUrl = playUrl;
  56. }
  57. }
  58.  
  59. }
  60.  
  61. }
  1. package net.bwie.surfaceviewvideolist.bean;
  2.  
  3. public class VideoBean {
  4.  
  5. private String title;
  6. private String playUrl;
  7.  
  8. public VideoBean(String title, String playUrl) {
  9. this.title = title;
  10. this.playUrl = playUrl;
  11. }
  12.  
  13. public String getTitle() {
  14. return title;
  15. }
  16.  
  17. public void setTitle(String title) {
  18. this.title = title;
  19. }
  20.  
  21. public String getPlayUrl() {
  22. return playUrl;
  23. }
  24.  
  25. public void setPlayUrl(String playUrl) {
  26. this.playUrl = playUrl;
  27. }
  28. }

Http:

  1. package net.bwie.surfaceviewvideolist.httpservice;
  2.  
  3. import net.bwie.surfaceviewvideolist.bean.KaiyanBean;
  4.  
  5. import retrofit2.Call;
  6. import retrofit2.http.GET;
  7.  
  8. public interface KaiyanHttpService {
  9.  
  10. @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")
  11. Call<KaiyanBean> getKaiyanCall();
  12.  
  13. }

封装类:

  1. /**
  2. * 能播放视频的SurfaceView,封装MediaPlayer
  3. * 提供一个public方法用于设置播放路径和播放的方法
  4. */
  5. public class VideoSurfaceView extends SurfaceView implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener {
  6. private SurfaceHolder mHolder;
  7. private MediaPlayer mMediaPlayer;
  8.  
  9. public VideoSurfaceView(Context context, AttributeSet attrs) {
  10. super(context, attrs);
  11.  
  12. init();
  13. }
  14.  
  15. private void init() {
  16. // 获得缓冲区持有者
  17. mHolder = getHolder();
  18. // 设置生命周期的回调
  19. mHolder.addCallback(this);
  20. }
  21.  
  22. // 设置播放路径并播放
  23. public void playVideo(String path) {
  24. if (mMediaPlayer == null) {
  25. mMediaPlayer = new MediaPlayer();
  26. // 准备完毕监听器
  27. mMediaPlayer.setOnPreparedListener(this);
  28. }
  29.  
  30. try {
  31. // 重置MediaPlayer
  32. mMediaPlayer.reset();
  33. // 设置画面播放源
  34. mMediaPlayer.setDisplay(mHolder);
  35. // 设置播放源
  36. mMediaPlayer.setDataSource(path);
  37. // 准备播放
  38. mMediaPlayer.prepareAsync();
  39. } catch (Exception e) {
  40. e.printStackTrace();
  41. Log.e("1507", e.getMessage());
  42. }
  43.  
  44. }
  45.  
  46. // 停止播放
  47. public void stop() {
  48. if (mMediaPlayer != null) {
  49. mMediaPlayer.stop();
  50. }
  51. }
  52.  
  53. @Override
  54. public void surfaceCreated(SurfaceHolder holder) {
  55.  
  56. }
  57.  
  58. @Override
  59. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  60.  
  61. }
  62.  
  63. @Override
  64. public void surfaceDestroyed(SurfaceHolder holder) {
  65. if (mMediaPlayer != null) {
  66. mMediaPlayer.release();// 释放资源
  67. mMediaPlayer = null;
  68. }
  69. }
  70.  
  71. @Override
  72. public void onPrepared(MediaPlayer mp) {
  73. mMediaPlayer.start();
  74. }
  75. }

Adapter:

  1. public class VideoListAdapter extends RecyclerView.Adapter<VideoListAdapter.ViewHolder> {
  2.  
  3. private Context mContext;
  4. private List<VideoBean> mDatas;
  5.  
  6. // 记录上一次播放的VideoView
  7. private VideoSurfaceView mPlayingView;
  8.  
  9. public VideoListAdapter(Context context, List<VideoBean> datas) {
  10. mContext = context;
  11. mDatas = datas;
  12. }
  13.  
  14. @Override
  15. public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  16. View itemView = LayoutInflater.from(mContext)
  17. .inflate(R.layout.item_video, parent, false);
  18. return new ViewHolder(itemView);
  19. }
  20.  
  21. @Override
  22. public void onBindViewHolder(final ViewHolder holder, int position) {
  23. final VideoBean videoBean = mDatas.get(position);
  24.  
  25. holder.mTitleTextView.setText(videoBean.getTitle());
  26.  
  27. // item刚复用进入屏幕时,无论是否播放都停止并隐藏
  28. holder.mSurfaceView.stop();
  29. holder.mSurfaceView.setVisibility(View.INVISIBLE);
  30.  
  31. holder.mPlayBtn.setOnClickListener(new View.OnClickListener() {
  32. @Override
  33. public void onClick(View v) {
  34.  
  35. // 下一次播放时,停止上一次播放
  36. if (mPlayingView != null) {
  37. mPlayingView.stop();
  38. mPlayingView.setVisibility(View.INVISIBLE);
  39. }
  40.  
  41. // 播放当前位置的视频
  42. holder.mSurfaceView.setVisibility(View.VISIBLE);// 显示
  43. holder.mSurfaceView.playVideo(videoBean.getPlayUrl());
  44.  
  45. mPlayingView = holder.mSurfaceView;
  46. }
  47. });
  48. }
  49.  
  50. @Override
  51. public int getItemCount() {
  52. return mDatas == null ? 0 : mDatas.size();
  53. }
  54.  
  55. static class ViewHolder extends RecyclerView.ViewHolder {
  56.  
  57. Button mPlayBtn;
  58. TextView mTitleTextView;
  59. TextView mProgressTextView;
  60. VideoSurfaceView mSurfaceView;
  61.  
  62. public ViewHolder(View itemView) {
  63. super(itemView);
  64.  
  65. mPlayBtn = ((Button) itemView.findViewById(R.id.play_btn));
  66. mTitleTextView = ((TextView) itemView.findViewById(R.id.title_tv));
  67. mProgressTextView = ((TextView) itemView.findViewById(R.id.progress_tv));
  68. mSurfaceView = ((VideoSurfaceView) itemView.findViewById(R.id.video_view));
  69. }
  70. }
  71.  
  72. }

别忘了加权限:

<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. 12-01 Java Scanner类,Scanner类中的nextLine()产生的换行符问题

    分析理解:Scanner sc = new Scanner(System.in); package cn.itcast_01; /* * Scanner:用于接收键盘录入数据. * * 前面的时候: ...

  2. How To Scan QRCode For UWP (1)

    本文将介绍实现一个类似于微信扫一扫功能的UI界面,后续会再实现具体的识别二维码的功能. 实例使用的Win10 SDK Version是Windows 10 Anniversary Edition(10 ...

  3. StringBuffer、StringBuilder、冒泡与选择排序、二分查找、基本数据类型包装类_DAY13

    1:数组的高级操作(预习) (1)数组:存储同一种数据类型的多个元素的容器. (2)特点:每个元素都有从0开始的编号,方便我们获取.专业名称:索引. (3)数组操作: A:遍历 public stat ...

  4. 分享一套简单的CodeSmith三层模板

    如果要连接mysql,需要安装驱动: https://cdn.mysql.com//Downloads/Connector-Net/mysql-connector-net-8.0.12.msi 连接字 ...

  5. 怎么样imageview实现铺满全屏

    <ImageView android:layout_width="match_parent" android:layout_height="match_parent ...

  6. Mysql压缩包版的安装方法详解

    Mysql安装的时候可以有msi安装和zip解压缩两种安装方式.zip压缩包解压到目录,要使用它还需对它进行一定的配置.下面对Mysql压缩包版的安装方法进行详细的描述,要是此文有不正确的认识,希望大 ...

  7. 全网最全的Windows下Anaconda2 / Anaconda3里Python语言实现定时发送微信消息给好友或群里(图文详解)

    不多说,直接上干货! 缘由: (1)最近看到情侣零点送祝福,感觉还是很浪漫的事情,相信有很多人熬夜为了给爱的人送上零点祝福,但是有时等着等着就睡着了或者时间并不是卡的那么准就有点强迫症了,这是也许程序 ...

  8. 开发工具 -- Eclipse快捷键

    [ALT+/]此快捷键为用户编辑的好帮手,能为用户提供内容的辅助,不要为记不全方法和属性名称犯愁,当记不全类.方法和属性的名字时,多体验一下[ALT+/]快捷键带来的好处吧.   [Ctrl+O]显示 ...

  9. Linux 启动过程详解

    目录 1. Linux启动过程 2. 启动过程概述 3. 引导加载阶段 4. 内核阶段 4.1 内核加载阶段 4.2 内核启动阶段 5. 早期的用户空间 6. 初始化过程 6.1 SysV init ...

  10. Vue + Element UI 实现权限管理系统 前端篇(九):接口格式定义

    接口请求格式定义 前台显示需要后台数据,我们这里先把前后端交互接口定义好,没有后台的时候,也方便用mock模拟. 接口定义遵循几个规范: 1. 接口按功能模块划分. 系统登录:登录相关接口 用户管理: ...