1

I have recently discovered abut Viewpager 2 and exoplayer and not sure how to integrate them both. Viewpager contains a list with video player and each takes up the full screen. You can swipe to move to the next video. Can anybody help me with a simple implementation of Exoplayer with Viewpager2

  • Refer this implemnetation (+ the answer to the question) to get started https://stackoverflow.com/questions/62499013/stop-and-release-exoplayer-from-viewpager-2 – PravyNandas Sep 11 '20 at 18:20

1 Answers1

0

Yes I can help you. It is a very simple implementation of viewpager2 with ExoPlayer. It will show you online videos and you can swipe these videos horizontally. Lets discuss it step by step:

Step 1: Add internet permission in your Manifest file:

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

Step 2: Add ExoPlayer dependency to your build.gradle

// exo player
implementation 'com.google.android.exoplayer:exoplayer:2.17.1'

Step 3 : Add the following code to your themes.xml

    <style name="ClickableView">
        <item name="colorControlHighlight">@android:color/darker_gray</item>
        <item name="android:background">?selectableItemBackgroundBorderless</item>
    </style>

Step 4: Create a controller layout file to control ExoPlayer named as custom_controller.xml. And then paste bellow code in that file.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="#80000000"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/exo_lock"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:padding="10dp"
        android:src="@drawable/ic_baseline_lock_open"
        android:theme="@style/ClickableView" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/sec_controlvid1"
        android:orientation="horizontal"
        android:layout_centerInParent="true">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/exo_rew"
            android:src="@drawable/ic_baseline_replay"
            android:layout_marginLeft="30dp"
            android:theme="@style/ClickableView"/>

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/exo_play"
            android:src="@drawable/ic_baseline_play_arrow"
            android:layout_marginHorizontal="30dp"
            android:theme="@style/ClickableView"/>

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/exo_pause"
            android:src="@drawable/ic_baseline_pause"
            android:layout_marginHorizontal="30dp"
            android:theme="@style/ClickableView"/>

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/exo_ffwd"
            android:layout_marginRight="30dp"
            android:src="@drawable/ic_baseline_forward"
            android:theme="@style/ClickableView"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/sec_controlvid2"
        android:orientation="vertical"
        android:padding="8dp"
        android:gravity="center"
        android:layout_alignParentBottom="true">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="8dp"
        android:gravity="center"
        android:layout_alignParentBottom="true">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/exo_position"
            android:textColor="@color/white"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="/"
            android:layout_marginHorizontal="4dp"
            android:textColor="#CBCDC8"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/exo_duration"
            android:layout_weight="1"
            android:textColor="#CBCDC8"/>

        <ImageView
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/ic_baseline_fullscreen"
            android:id="@+id/bt_fullscreen"
            android:theme="@style/ClickableView"/>

    </LinearLayout>
    <com.google.android.exoplayer2.ui.DefaultTimeBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/exo_progress"
        app:unplayed_color="#42454E"
        app:buffered_color="#95989F"
        app:played_color="#FF0000"
        app:scrubber_color="#FF0000"
        android:layout_alignParentBottom="true"
        android:layout_marginTop="-8dp"/>
    </LinearLayout>
</RelativeLayout>

Step 5: Create a layout file for representing items in viewpager named as video_card_item.xml and write the following code in it:

<?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"
android:gravity="center_vertical"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.exoplayer2.ui.PlayerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:id="@+id/statusSliderVideo"
    app:use_controller="true"
    android:background="@android:color/background_dark"
    app:player_layout_id="@layout/exo_player_view"
    app:controller_layout_id="@layout/custom_controller"/>

<ImageView
    android:id="@+id/statusSliderThumbnailImage"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:padding="10dp"
    android:scaleType="fitCenter"
    android:src="@drawable/ic_default_image" />

<ImageView
    android:id="@+id/playPauseBtn"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_centerInParent="true"
    android:src="@drawable/ic_play"
    app:tint="@color/white" />
<ProgressBar
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:visibility="gone"
    android:id="@+id/progress_bar"
    android:layout_centerInParent="true"/>
</RelativeLayout>

Step 6 : Create adapter class for viewpager items named as VideoSliderAdapter.java and write bellow code in it:

package com.example.practiceproject;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.ui.PlayerView;

import java.util.ArrayList;

public class VideoSliderAdapter extends RecyclerView.Adapter<VideoSliderAdapter.ViewHolder> {
    private Context context;
    private ArrayList<String> pathsList;
    private AppCompatActivity activity;

    private boolean isFullScreen = false;
    public static boolean isFullLock = false;


    public VideoSliderAdapter(Context context, ArrayList<String> pathsList, AppCompatActivity activity) {
        this.context = context;
        this.pathsList = pathsList;
        this.activity = activity;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.video_card_item, parent, false);
        return new ViewHolder(view);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
                holder.thumbnailImage.setImageBitmap(ThumbnailUtils.createVideoThumbnail(pathsList.get(position),
                        MediaStore.Video.Thumbnails.FULL_SCREEN_KIND));


                // get data
                Uri videoUri = Uri.parse(pathsList.get(position));

                holder.bt_fullscreen.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (!isFullScreen) {
                            holder.bt_fullscreen.setImageDrawable(
                                    ContextCompat.getDrawable(context, R.drawable.ic_baseline_fullscreen_exit)
                            );
                            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
                        } else {
                            holder.bt_fullscreen.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_baseline_fullscreen));
                            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                        }
                        isFullScreen = !isFullScreen;
                    }
                });



                holder.bt_lockscreen.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (isFullLock) {
                            holder.bt_lockscreen.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_baseline_lock_open));
                        } else {
                            holder.bt_lockscreen.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_baseline_lock));
                        }

                        isFullLock = !isFullLock;
                        lockScreen(isFullLock, holder.sec_mid, holder.sec_bottom);

                    }
                });


                holder.playPauseBtn.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {

                        holder.playPauseBtn.setVisibility(View.GONE);
//                        holder.thumbnailImage.setVisibility(View.GONE);
                        holder.playerView.setVisibility(View.VISIBLE);
                        holder.simpleExoPlayer = new SimpleExoPlayer.Builder(context)
                                .setSeekBackIncrementMs(5000)
                                .setSeekForwardIncrementMs(5000)
                                .build();
                        holder.playerView.setPlayer(holder.simpleExoPlayer);
                        holder.playerView.setKeepScreenOn(true);
                        holder.simpleExoPlayer.addListener(new Player.Listener() {
                            @Override
                            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                                if (playbackState == Player.STATE_BUFFERING) {
                                    holder.progressBar.setVisibility(View.VISIBLE);
                                } else if (playbackState == Player.STATE_READY) {
                                    holder.progressBar.setVisibility(View.GONE);
                                }
                            }
                        });

                        MediaItem mediaItem = MediaItem.fromUri(videoUri);
                        holder.simpleExoPlayer.setMediaItem(mediaItem);
                        holder.simpleExoPlayer.prepare();
                        holder.simpleExoPlayer.play();
                    }
                });

    }

    private void lockScreen(boolean isFullLock, LinearLayout sec_mid, LinearLayout sec_bottom) {
        if (isFullLock) {
            sec_mid.setVisibility(View.INVISIBLE);
            sec_bottom.setVisibility(View.INVISIBLE);
        } else {
            sec_mid.setVisibility(View.VISIBLE);
            sec_bottom.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public int getItemCount() {
        return pathsList.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        PlayerView playerView;
        ImageView thumbnailImage;
        ImageView playPauseBtn;
        ImageView bt_fullscreen, bt_lockscreen;
        SimpleExoPlayer simpleExoPlayer;
        ProgressBar progressBar;
        LinearLayout sec_mid, sec_bottom;

        public ViewHolder(@NonNull View view) {
            super(view);
            playerView = view.findViewById(R.id.statusSliderVideo);
            thumbnailImage = view.findViewById(R.id.statusSliderThumbnailImage);
            playPauseBtn = view.findViewById(R.id.playPauseBtn);
            progressBar = view.findViewById(R.id.progress_bar);
            bt_fullscreen = view.findViewById(R.id.bt_fullscreen);
            bt_lockscreen = view.findViewById(R.id.exo_lock);
            sec_mid = view.findViewById(R.id.sec_controlvid1);
            sec_bottom = view.findViewById(R.id.sec_controlvid2);
        }
    }
}

Step 7 : Paste following code in your activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <androidx.viewpager2.widget.ViewPager2
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:clipToPadding="true"
        android:foregroundGravity="center"
        android:overScrollMode="never"
        android:id="@+id/videoViewPager"/>
</LinearLayout>

Step 8 : Paste bellow code in your MainActivity.java:

package com.example.practiceproject;

import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;

import android.os.Bundle;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ViewPager2 viewPager;
    private VideoSliderAdapter myAdapter;
    ArrayList<String> videoPaths;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager = findViewById(R.id.videoViewPager);
        videoPaths = new ArrayList<>();
        videoPaths.add("http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4");
        videoPaths.add("http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4");
        videoPaths.add("http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4");
        videoPaths.add("http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4");
        videoPaths.add("http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4");
        // add paths for video simllarly

        myAdapter = new VideoSliderAdapter(getApplicationContext(), videoPaths,
                MainActivity.this);
        viewPager.setAdapter(myAdapter);
        viewPager.setPadding(10, 0, 10, 0);
    }
}

Completed

Now you are good to go. Enjoy the app.. Best of Luck.

If you want to get project files (Source Code) for more simplicity, you can get source code from my github profile. link : https://github.com/AbdullahProgrammer426351/Custom-Video-Slider-with-Exo-Player-and-ViewPager2