テクスチャ ビューとメディア プレーヤーを使用して実装されたビデオ プレーヤーの Recycler ビューを実装しました。
リストを下にスクロールすると、項目をクリックするとビデオが再生されます。ただし、リサイクラー ビューでは、ビューが画面から消えると、再利用のためにリサイクルされます。上にスクロールすると、すべてのビューが空白 (黒) になります。
ユーザーがビデオを画面外にスクロールすると一時停止し、そのビデオへの参照を保持して、そのビデオに戻るとその時点から再生されるようにする機能を追加しようとしています。
これを確認しましたが、ビデオをダウンロードするのではなく、ストリーミングしたいだけです。私は私のためにこれを行う人を探しているのではありません。私はいくつかの指針を探しており、誰かがこれに関する知識を共有できることを望んでいます...事前に感謝します
これは私がこれまでに行ったことです:
ビデオプレーヤー
public class CustomVideoPlayer implements TextureView.SurfaceTextureListener, VideoControllerView.MediaPlayerControl, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnVideoSizeChangedListener {
private Context mContext;
private String mUrl;
private MediaPlayer mMediaPlayer;
private Surface mSurface;
private VideoControllerView mControllerView;
private TextureView mTextureView;
private CardView mCardView;
private ProgressBar mProgress;
private FrameLayout mView;
private RelativeLayout mLayout;
public CustomVideoPlayer(Context ctx, TextureView view, ProgressBar progressDialog, FrameLayout holderView){
this.mContext = ctx;
mTextureView = view;
mTextureView.setSurfaceTextureListener(this);
mProgress = progressDialog;
mControllerView = new VideoControllerView(ctx);
mView = holderView;
mTextureView.setOnTouchListener(new ControlTouchListener());
}
@Override
public boolean canPause() {
return true;
}
@Override
public boolean canSeekBackward() {
return true;
}
@Override
public boolean canSeekForward() {
return true;
}
@Override
public int getBufferPercentage() {
return 0;
}
@Override
public int getCurrentPosition() {
return mMediaPlayer.getCurrentPosition();
}
@Override
public int getDuration() {
return mMediaPlayer.getDuration();
}
@Override
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
@Override
public void pause() {
mMediaPlayer.pause();
}
@Override
public void seekTo(int i) {
mMediaPlayer.seekTo(i);
}
@Override
public void start() {
mMediaPlayer.start();
}
@Override
public boolean isFullScreen() {
return false;
}
@Override
public void toggleFullScreen() {
}
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
}
@Override
public void onCompletion(MediaPlayer mp) {
}
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mSurface = new Surface(surface);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
public void changePlayState(){
if(mMediaPlayer.isPlaying()){
mMediaPlayer.pause();
}else{
mMediaPlayer.start();
}
}
public void startVideo(String url){
if(mMediaPlayer!=null){
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = new MediaPlayer();
}else{
mMediaPlayer = new MediaPlayer();
}
if(!mMediaPlayer.isPlaying()){
try {
mMediaPlayer.setSurface(mSurface);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource(url);
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
mMediaPlayer.setOnPreparedListener(this);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onPrepared(MediaPlayer mp) {
Log.i(VersysVideoPlayer.class.getSimpleName(), "ON PREPARED CALLED");
mControllerView.setMediaPlayer(this);
mControllerView.setAnchorView(mView);
mControllerView.show();
mProgress.setVisibility(View.GONE);
mMediaPlayer.start();
}
//Touch listener to display video controls
class ControlTouchListener implements View.OnTouchListener{
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
mControllerView.show();
}
return false;
}
}
}
アクティビティ/アダプター
public class VideoViewListActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_view_list);
//Create instance of Recycler view
final RecyclerView videoList = (RecyclerView) findViewById(R.id.feed_list);
LinearLayoutManager llm = new LinearLayoutManager(this);
videoList.setLayoutManager(llm);
videoList.setHasFixedSize(true);
final List<String> list = new ArrayList<>();
list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
list.add("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
final VideoAdapter adapter = new VideoAdapter(list, this);
videoList.setAdapter(adapter);
videoList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
TextureView view = adapter.getVideoPlayer();
Log.i("PERCENTAGE VISIBLE: ", String.valueOf(getVisiblePercent(adapter.getVideoPlayer())));
if(getVisiblePercent(view)==100) {
return;
}
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_video_view_list, menu);
return true;
}
public static int getVisiblePercent(View v) {
if (v.isShown()) {
Rect r = new Rect();
v.getGlobalVisibleRect(r);
double sVisible = r.width() * r.height();
double sTotal = v.getWidth() * v.getHeight();
return (int) (100 * sVisible / sTotal);
} else {
return -1;
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Recycler View Adapter
*/
class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoFeedHolder> {
public TextureView mPreview;
private CardView mCardView;
private List<String> mUrls;
private Context mContext;
private Surface mSurface;
VideoControllerView controller;
private View mAnchor;
private ProgressBar mProgressDialog;
private ImageView mHolder;
private int mPosition;
private VersysVideoPlayer mVideoPlayer;
OnItemClickListener mItemClickListener;
public VideoAdapter(List<String> url, Context ctx) {
mUrls = url;
mContext = ctx;
controller = new VideoControllerView(ctx);
}
@Override
public VideoAdapter.VideoFeedHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.video_item_feed, viewGroup, false);
VideoFeedHolder holder = new VideoFeedHolder(v);
return holder;
}
@Override
public void onBindViewHolder(final VideoFeedHolder videoFeedHolder, final int i) {
final VersysVideoPlayer videoPlayer = new VersysVideoPlayer(mContext, videoFeedHolder.mTexturePreview, mProgressDialog, videoFeedHolder.controlHolder);
videoFeedHolder.placeholder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
videoPlayer.startVideo(mUrls.get(i));
videoFeedHolder.placeholder.setVisibility(View.GONE);
videoFeedHolder.bar.setVisibility(View.VISIBLE);
}
});
mPosition = i;
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public String getUrl() {
return mUrls.get(mPosition);
}
@Override
public int getItemCount() {
return mUrls.size();
}
public TextureView getVideoPlayer() {
return mPreview;
}
public class VideoFeedHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextureView mTexturePreview;
ProgressBar bar;
ImageView placeholder;
FrameLayout controlHolder;
RelativeLayout touchLayout;
public VideoFeedHolder(View itemView) {
super(itemView);
mTexturePreview = (TextureView) itemView.findViewById(R.id.video_player);
mPreview = mTexturePreview;
mCardView = (CardView) itemView.findViewById(R.id.cv);
bar = (ProgressBar)itemView.findViewById(R.id.buffereing);
placeholder = (ImageView) itemView.findViewById(R.id.holder);
mProgressDialog = bar;
controlHolder = (FrameLayout) itemView.findViewById(R.id.media_controller_anchor);
}
@Override
public void onClick(View v) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(v, getAdapterPosition());
}
}
}
}
}
ビデオ フィード アイテム XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="400dp"
android:id="@+id/cv">
<RelativeLayout
android:id="@+id/anchor"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/detail_layout"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/profile_pic"
android:background="@drawable/profiler"
android:layout_marginLeft="10dp"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:id="@+id/user_name"
android:layout_alignTop="@+id/profile_pic"
android:layout_toRightOf="@+id/profile_pic"
android:text="Joe Bloggs"
android:layout_marginLeft="10dp"
android:textColor="#000000"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/date"
android:layout_below="@+id/user_name"
android:layout_toRightOf="@+id/profile_pic"
android:layout_marginLeft="10dp"
android:text="10 Aug 2015"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/desc"
android:layout_below="@+id/profile_pic"
android:layout_marginLeft="10dp"
android:text="This a sample video of a bird getting hit on the head and a rabbit waking from a nap!!"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
<RelativeLayout
android:layout_below="@+id/detail_layout"
android:layout_margin="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextureView
android:id="@+id/video_player"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="@+id/media_controller_anchor"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</FrameLayout>
<ImageView
android:id="@+id/holder"
android:layout_centerInParent="true"
android:background="@drawable/default_video_poster"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/buffereing"
android:visibility="gone"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>