I have a app where I make a API call and get a arraylist of videos, which I play in a viewpager using a adapter. When I scroll the viewpager, the video playing before still keeps playing and even after I scroll again. I want it so that the video should only play when the user is on that particular viewpager view and when user scrolls the video should stop.
Code for VideoAdapter class
public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHolder> {
ArrayList<VideoModel> videos;
public VideoAdapter(ArrayList<VideoModel> videos) {
this.videos = videos;
}
@NonNull
@Override
public VideoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.video_lyt,parent,false);
return new VideoViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull VideoViewHolder holder, int position) {
holder.setData(videos.get(position));
}
@Override
public int getItemCount() {
return videos.size();
}
class VideoViewHolder extends RecyclerView.ViewHolder {
PlayerView playerview;
TextView title,desc;
SimpleExoPlayer simpleExoPlayer;
public VideoViewHolder(@NonNull View itemView) {
super(itemView);
playerview = itemView.findViewById(R.id.playerView);
title = itemView.findViewById(R.id.titleTextView);
desc = itemView.findViewById(R.id.descTextView);
}
void setData(VideoModel videoModel)
{
Log.d("setting","data");
simpleExoPlayer = new SimpleExoPlayer.Builder(itemView.getContext()).build();
playerview.setPlayer(simpleExoPlayer);
title.setText(videoModel.getUser_info().getTitle());
desc.setText(videoModel.getDesc());
MediaItem mediaItem = MediaItem.fromUri(videoModel.getUrl());
simpleExoPlayer.setRepeatMode(Player.REPEAT_MODE_ONE);
playerview.setUseController(false);
//making the video fit the entire screen
playerview.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL);
simpleExoPlayer.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
simpleExoPlayer.addMediaItem(mediaItem);
simpleExoPlayer.setPlayWhenReady(false);
simpleExoPlayer.prepare();
}
}
Code for MainActivity
public class MainActivity extends AppCompatActivity {
ViewPager2 viewPager2;
ArrayList<VideoModel> videos, videosSend;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
viewPager2 = (ViewPager2) findViewById(R.id.viewpagerVideos);
videos = new ArrayList<>();
videosSend = new ArrayList<>();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("myapi")
.addConverterFactory(GsonConverterFactory.create())
.build();
APICall apiCall = retrofit.create(APICall.class);
Call<VideoAPIData> call = apiCall.getVideos();
call.enqueue(new Callback<VideoAPIData>() {
@Override
public void onResponse(Call<VideoAPIData> call, Response<VideoAPIData> response) {
videos = response.body().getMsg();
Log.d("API","Success");
viewPager2.setAdapter(new VideoAdapter(videos));
}
@Override
public void onFailure(Call<VideoAPIData> call, Throwable t) {
Log.d("API Fail", t.getMessage());
}
});
}
Thanks to Nitish Chaudhary I have solved this issue
This is the updated Adapter class after the solution
public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHolder> {
ArrayList<VideoModel> videos;
SimpleExoPlayer simpleExoPlayer;
public VideoAdapter(ArrayList<VideoModel> videos) {
this.videos = videos;
}
@NonNull
@Override
public VideoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.video_lyt,parent,false);
return new VideoViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull VideoViewHolder holder, int position) {
holder.setData(videos.get(position));
}
@Override
public int getItemCount() {
return videos.size();
}
class VideoViewHolder extends RecyclerView.ViewHolder {
PlayerView playerview;
TextView title,desc;
public VideoViewHolder(@NonNull View itemView) {
super(itemView);
playerview = itemView.findViewById(R.id.playerView);
title = itemView.findViewById(R.id.titleTextView);
desc = itemView.findViewById(R.id.descTextView);
}
void setData(VideoModel videoModel)
{
simpleExoPlayer = new SimpleExoPlayer.Builder(itemView.getContext()).build();
playerview.setPlayer(simpleExoPlayer);
title.setText(videoModel.getUser_info().getTitle());
desc.setText(videoModel.getDesc());
MediaItem mediaItem = MediaItem.fromUri(videoModel.getUrl());
simpleExoPlayer.setRepeatMode(Player.REPEAT_MODE_ONE);
playerview.setUseController(false);
//making the video fit the entire screen
playerview.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL);
simpleExoPlayer.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
simpleExoPlayer.addMediaItem(mediaItem);
//this code sets the playwhenready(true) for only the first video to be shown at the launch of app
if(videoModel.getPlaying()!=null)
{
simpleExoPlayer.setPlayWhenReady(true);
}
else{
simpleExoPlayer.setPlayWhenReady(false);
}
simpleExoPlayer.prepare();
}
}
//this is the change that solves this issue
@Override
public void onViewAttachedToWindow(@NonNull VideoViewHolder holder) {
super.onViewAttachedToWindow(holder);
holder.playerview.getPlayer().setPlayWhenReady(true);
holder.playerview.getPlayer().prepare();
}
@Override
public void onViewDetachedFromWindow(@NonNull VideoViewHolder holder) {
super.onViewDetachedFromWindow(holder);
holder.playerview.getPlayer().setPlayWhenReady(false);
holder.playerview.getPlayer().stop();
}
}
You can override onViewAttachedToWindow
and onViewDetachedFromWindow
and play/pause your videos only when view is visible on the user.
RecyclerAdapter
public class VideoAdapter extends RecyclerView.Adapter {
@Override
@Override
public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
//play video
}
@Override
public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) {
super.onViewDetachedFromWindow(holder);
//pause video
}