主界面
package net.bwie.surfaceviewvideolist; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.RecyclerView; import android.util.Log; import net.bwie.surfaceviewvideolist.adapter.VideoListAdapter; import net.bwie.surfaceviewvideolist.bean.KaiyanBean; import net.bwie.surfaceviewvideolist.bean.VideoBean; import net.bwie.surfaceviewvideolist.httpservice.KaiyanHttpService; import java.util.ArrayList; import java.util.List; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; /** * 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) { } }
对应布局
<?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>
写一个播放的方法
package net.bwie.surfaceviewvideolist.widget; import android.content.Context; import android.media.MediaPlayer; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * 能播放视频的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(); } }
适配器
package net.bwie.surfaceviewvideolist.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import net.bwie.surfaceviewvideolist.R; import net.bwie.surfaceviewvideolist.bean.VideoBean; import net.bwie.surfaceviewvideolist.widget.VideoSurfaceView; import java.util.List; 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)); } } }
对应布局
<?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>
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(); }
以及两个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; } }
权限
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>