Tag

android

Browsing

DateTime is a common utility in Android. In these days most of the project required date and time formatting in Android. So we are building a plug and play solution. I hope each developer will keep this utility in own inbox for a Time Saving purpose. In this tutorials, we demonstrate different-different date formatting and parsing

SimpleDateFormat is a java class which extends the DateFormat java class. It is used for normalization, formatting and parsing date in a locale-sensitive manner.

SimpleDateFormat is used for below utility in Android

  • Formatting – It allows for formatting Date to Text in Android any given locale.
  • Parsing – You can parse any Text in Date object by using SimpleDateFormat

Some specific Letter is used for represent Date or Time Component in Android. You can read Google Official site.

Formatting

Here we discuss some date format my intention is to cover each combination of date format.

DATE_FORMAT_1 = hh:mm a
The output will be -: 10:37 am

DATE_FORMAT_2 = h:mm a
Output will be -: 10:37 am

DATE_FORMAT_3 = yyyy-MM-dd
The output will be -: 2018-12-05

DATE_FORMAT_4 = dd-MMMM-yyyy
The output will be -: 05-December-2018

DATE_FORMAT_5 = dd MMMM yyyy
The output will be -: 05 December 2018

DATE_FORMAT_6 = dd MMMM yyyy zzzz
The output will be -: 05 December 2018 UTC

DATE_FORMAT_7 = EEE, MMM d, ''yy
The output will be -: Wed, Dec 5, '18

DATE_FORMAT_8 = yyyy-MM-dd HH:mm:ss
The Output will be -: 2018-12-05 10:37:43

DATE_FORMAT_9 = h:mm a dd MMMM yyyy
The output will be -: 10:37 am 05 December 2018

DATE_FORMAT_10 = K:mm a, z
The output will be -: 10:37 am, UTC

DATE_FORMAT_11 = hh 'o''clock' a, zzzz
The output will be -: 10 o'clock am, UTC

DATE_FORMAT_12 = yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
The output will be -: 2018-12-05T10:37:43.937Z

DATE_FORMAT_13 = E, dd MMM yyyy HH:mm:ss z
The output will be -: Wed, 05 Dec 2018 10:37:43 UTC

DATE_FORMAT_14 = yyyy.MM.dd G 'at' HH:mm:ss z
The output will be -: 2018.12.05 AD at 10:37:43 UTC

DATE_FORMAT_15 = yyyyy.MMMMM.dd GGG hh:mm aaa
The output will be -: 02018.D.05 AD 10:37 am

DATE_FORMAT_16 = EEE, d MMM yyyy HH:mm:ss Z
The output will be -: Wed, 5 Dec 2018 10:37:43 +0000

DATE_FORMAT_17 = yyyy-MM-dd'T'HH:mm:ss.SSSZ
The output will be -: 2018-12-05T10:37:43.946+0000

DATE_FORMAT_18 = yyyy-MM-dd'T'HH:mm:ss.SSSXXX
The output will be -: 2018-12-05T10:37:43.949Z

DATE_FORMAT_19 = dd-MMM-yyyy
The output will be -: 05-Dec-2018

All above date format combination. Now comes utility class.

Get Current Date

    /**
     * Default date format 
     */
    public static final String DATE_FORMAT_2 = "dd-MMM-yyyy";
    
    public static String getCurrentDate() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_1);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date today = Calendar.getInstance().getTime();
        return dateFormat.format(today);
    }

Get current Time


    /**
     * Default time format
     */
    public static final String DATE_FORMAT_1 = "hh:mm a";
    
    public static String getCurrentTime() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_1);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date today = Calendar.getInstance().getTime();
        return dateFormat.format(today);
    }

Get Date and Time from Timestamp

  /**
     * 
     * @param time in milliseconds (Timestamp)
     * @param mDateFormat SimpleDateFormat
     * @return
     */
    public static String getDateTimeFromTimeStamp(Long time, String mDateFormat) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(mDateFormat);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date dateTime = new Date(time);
        return dateFormat.format(dateTime);
    }

How to use it

        /**
         * Get current date example 1
         */
        String mCurrentDate = DateUtils.getCurrentDate();
        
        /**
         * Get current time example 2
         */
        String mCurrentTime = DateUtils.getCurrentTime();

       /**
        * Date Format example 3
        */
        public static final String DATE_FORMAT = "dd-MMM-yyyy";
        String mDateTime = DateUtils.getDateFromTimeStamp(System.currentTimeMillis(), DATE_FORMAT);

Date Parsing in Android

Let’s take few example of date parsing

Get Timestamp from DateTime in Android

 /**
     * Get Timestamp from date and time
     * @param mDateTime datetime String
     * @param mDateFormat Date Format 
     * @return
     * @throws ParseException
     */
    public static long getTimeStampFromDateTime(String mDateTime, String mDateFormat) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat(mDateFormat);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date = dateFormat.parse(mDateTime);
        return date.getTime();
    }  

Get DateTime from Date instase

   /**
     * Return  datetime String from date object  
     * @param mDateFormat format of date 
     * @param date date object that you want to parse
     * @return
     */
    public static String formatDateTimeFromDate(String mDateFormat, Date date) {
        if (date == null) {
            return null;
        }
        return DateFormat.format(mDateFormat, date).toString();
    }

Convert DateTime String to another DateTime String format

This is very useful and confusing utility in Android

   /**
     *  Convert one date format string  to another date format string in android
     * @param inputDateFormat Input SimpleDateFormat
     * @param outputDateFormat Output SimpleDateFormat
     * @param inputDate  input Date String
     * @return
     * @throws ParseException
     */
    public static String formatDateFromDateString(String inputDateFormat, String outputDateFormat, String inputDate) throws ParseException {
        Date mParsedDate;
        String mOutputDateString;
        SimpleDateFormat mInputDateFormat = new SimpleDateFormat(inputDateFormat, java.util.Locale.getDefault());
        SimpleDateFormat mOutputDateFormat = new SimpleDateFormat(outputDateFormat, java.util.Locale.getDefault());
        mParsedDate = mInputDateFormat.parse(inputDate);
        mOutputDateString = mOutputDateFormat.format(mParsedDate);
        return mOutputDateString;

    }

How to use

       /**
         * Date Format example 4
         */
        public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
        String mDateTimeString = "2018-12-05 10:37:43";
        try {
            long mTimestamp = DateUtils.getTimeStampFromDateTime(mDateTimeString, DATE_FORMAT);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        /**
         * Get current datetime example 5
         */
        public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
        String mDateTime = DateUtils.formatDateTimeFromDate(DATE_FORMAT, Calendar.getInstance().getTime());
   
   
       
      /**  Example 6
       * DateTime Input Format
       */
       public static final String DATE_INPUT_FORMAT = "yyyy-MM-dd HH:mm:ss";

      /**
       * DateTime Output Format
       */
      public static final String DATE_OUTPUT_FORMAT = "dd-MMM-yyyy";

       String mDateTimeString = "2018-12-05 10:37:43";

        String mDateTime = null;
        try {
            mDateTime = DateUtils.formatDateFromDateString(DATE_INPUT_FORMAT, DATE_OUTPUT_FORMAT, mDateTimeString);
        } catch (ParseException e) {
            e.printStackTrace();
        }

      The output is - 05-Dec-2018;
        

The complete Utitliy seems like below

package com.androidwave.datetimeutils.utils;


import android.text.format.DateFormat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class DateUtils {

    private static final String TAG = "DateUtils";

    public static final String DATE_FORMAT_1 = "hh:mm a";
    public static final String DATE_FORMAT_2 = "h:mm a";
    public static final String DATE_FORMAT_3 = "yyyy-MM-dd";
    public static final String DATE_FORMAT_4 = "dd-MMMM-yyyy";
    public static final String DATE_FORMAT_5 = "dd MMMM yyyy";
    public static final String DATE_FORMAT_6 = "dd MMMM yyyy zzzz";
    public static final String DATE_FORMAT_7 = "EEE, MMM d, ''yy";
    public static final String DATE_FORMAT_8 = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT_9 = "h:mm a dd MMMM yyyy";
    public static final String DATE_FORMAT_10 = "K:mm a, z";
    public static final String DATE_FORMAT_11 = "hh 'o''clock' a, zzzz";
    public static final String DATE_FORMAT_12 = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
    public static final String DATE_FORMAT_13 = "E, dd MMM yyyy HH:mm:ss z";
    public static final String DATE_FORMAT_14 = "yyyy.MM.dd G 'at' HH:mm:ss z";
    public static final String DATE_FORMAT_15 = "yyyyy.MMMMM.dd GGG hh:mm aaa";
    public static final String DATE_FORMAT_16 = "EEE, d MMM yyyy HH:mm:ss Z";
    public static final String DATE_FORMAT_17 = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
    public static final String DATE_FORMAT_18 = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";


    public static String getCurrentDate() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_1);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date today = Calendar.getInstance().getTime();
        return dateFormat.format(today);
    }

    public static String getCurrentTime() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_1);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date today = Calendar.getInstance().getTime();
        return dateFormat.format(today);
    }

    /**
     * @param time        in milliseconds (Timestamp)
     * @param mDateFormat SimpleDateFormat
     * @return
     */
    public static String getDateTimeFromTimeStamp(Long time, String mDateFormat) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(mDateFormat);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date dateTime = new Date(time);
        return dateFormat.format(dateTime);
    }

    /**
     * Get Timestamp from date and time
     *
     * @param mDateTime   datetime String
     * @param mDateFormat Date Format
     * @return
     * @throws ParseException
     */
    public static long getTimeStampFromDateTime(String mDateTime, String mDateFormat) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat(mDateFormat);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date = dateFormat.parse(mDateTime);
        return date.getTime();
    }

    /**
     * Return  datetime String from date object
     *
     * @param mDateFormat format of date
     * @param date        date object that you want to parse
     * @return
     */
    public static String formatDateTimeFromDate(String mDateFormat, Date date) {
        if (date == null) {
            return null;
        }
        return DateFormat.format(mDateFormat, date).toString();
    }

    /**
     *  Convert one date format string  to another date format string in android
     * @param inputDateFormat Input SimpleDateFormat
     * @param outputDateFormat Output SimpleDateFormat
     * @param inputDate  input Date String
     * @return
     * @throws ParseException
     */
    public static String formatDateFromDateString(String inputDateFormat, String outputDateFormat, String inputDate) throws ParseException {
        Date mParsedDate;
        String mOutputDateString;
        SimpleDateFormat mInputDateFormat = new SimpleDateFormat(inputDateFormat, java.util.Locale.getDefault());
        SimpleDateFormat mOutputDateFormat = new SimpleDateFormat(outputDateFormat, java.util.Locale.getDefault());
        mParsedDate = mInputDateFormat.parse(inputDate);
        mOutputDateString = mOutputDateFormat.format(mParsedDate);
        return mOutputDateString;

    }
}

1. Switch camera rear to front & front-rear in Camera2 API

In previous 2 blogs, I have explained Video Recoding using Camera2 API. Furtermore In this tutorials I’m explaing about swich camera front-rear via-varsa. As you we have build a CameraVideoFragment.java utility class.

2. Declare below variable in CameraVideoFragment.java.

    /* 0 forback camera 
     * 1 for front camera 
     * Initlity default camera is front camera    
     */
    public static final String CAMERA_FRONT = "1";
    public static final String CAMERA_BACK = "0";
    private String cameraId = CAMERA_FRONT;

3. Check available cameras

We can fetch all available cameras from Camera Manager instase by calling getCameraIdList .It’s return all available via getCameraIdList() (front/rear), then you can find the best camera that you want to use or suits your need.

You can get CameraCharacteristics by using camera ID. You can manage facing, resolution and filter also. In variable declear block we define front and back camera id.

In this tutorial, the front camera is the default camera.

   CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);

As above private String cameraId = CAMERA_FRONT; we set default camera is front camera, So cameraId have instance of front camera.

4. Furthermore we can Switch Camera usign below code

 public void switchCamera() {
        if (cameraId.equals(CAMERA_FRONT)) {
            cameraId = CAMERA_BACK;
            closeCamera();
            reopenCamera();


        } else if (cameraId.equals(CAMERA_BACK)) {
            cameraId = CAMERA_FRONT;
            closeCamera();
            reopenCamera();

        }
    }

After changing cameraId we just close the previous camera and reopen it.

 public void reopenCamera() {
        if (mTextureView.isAvailable()) {
            openCamera(mTextureView.getWidth(), mTextureView.getHeight());
        } else {
            mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
        }
    }

Finally just call switchCamera() method in child Fragment

Download Sample Project- Switch Camera in Camera2 API Android

 
If you have any query, feel free to connect us.

In the previous tutorial, we demonstrate video streaming over the Internet using ExoPlayer. Somehow you missed previous articles you must read this ExoPlayer in Android for better understanding. In a previous blog, you get an idea about ExoPlayer core functionality, DASH and UI library module.

I hope you read my previous tutorials(I can assume you have basic knowledge about ExoPlayer). In this tutorial, I will describe how to implement video playback in the RecyclerView Android. Just like some popular application eg. Magisto, Facebook, Twitter, Instagram.

This article based on ExoPlayer. In case some things miss in this article download full source and a working sample apk is there.

Before starting to think in 2 min what we needed to solve.

  • First problem is managing ExoPlayer playback
  • Second is we need to know which view on the scrolled list is currently active. So we can initialize and release ExoPlayer intense in RecylerView
  • Create Project

    Simply go to file menu and create a project and add the ExoPlayer dependency in build.gradle.

        implementation 'com.google.android.exoplayer:exoplayer:2.7.3'
        implementation 'org.jsoup:jsoup:1.10.3'
    

    The complete project hierarchy seems like image

    ExoPlayer in RecyclerView in android tutorials
    ExoPlayer in RecyclerView in android

    Create a custom RecyclerView with ExoPlayerRecyclerView name

    Now comes in first problem is

    how to manage ExoPlayer playback?

    Create a class ExoPlayerRecyclerView.java which extend RecyclerView
    Furthermore we fetch start position and end position of view from LayoutManager after that calculate target position.
    Here now on target position, we will add ExoPlayerView and set ExoPlayer.

      //play the video in the row
        public void playVideo() {
            int startPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
            int endPosition = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
    
            if (endPosition - startPosition > 1) {
                endPosition = startPosition + 1;
            }
    
            if (startPosition < 0 || endPosition < 0) {
                return;
            }
    
            int targetPosition;
            if (startPosition != endPosition) {
                int startPositionVideoHeight = getVisibleVideoSurfaceHeight(startPosition);
                int endPositionVideoHeight = getVisibleVideoSurfaceHeight(endPosition);
                targetPosition = startPositionVideoHeight > endPositionVideoHeight ? startPosition : endPosition;
            } else {
                targetPosition = startPosition;
            }
    
            if (targetPosition < 0 || targetPosition == playPosition) {
                return;
            }
            playPosition = targetPosition;
            if (videoSurfaceView == null) {
                return;
            }
            videoSurfaceView.setVisibility(INVISIBLE);
            removeVideoView(videoSurfaceView);
    
            // get target View targetPosition in RecyclerView
            int at = targetPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
    
            View child = getChildAt(at);
            if (child == null) {
                return;
            }
    
            VideoRecyclerViewAdapter.ViewHolder holder
                    = (VideoRecyclerViewAdapter.ViewHolder) child.getTag();
            if (holder == null) {
                playPosition = -1;
                return;
            }
            mCoverImage = holder.mCover;
            FrameLayout frameLayout = holder.itemView.findViewById(R.id.video_layout);
            frameLayout.addView(videoSurfaceView);
            addedVideo = true;
            rowParent = holder.itemView;
            videoSurfaceView.requestFocus();
            // Bind the player to the view.
            videoSurfaceView.setPlayer(player);
    
            // Measures bandwidth during playback. Can be null if not required.
            DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
            // Produces DataSource instances through which media data is loaded.
    
            DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(appContext,
                    Util.getUserAgent(appContext, "android_wave_list"), defaultBandwidthMeter);
            // This is the MediaSource representing the media to be played.
            String uriString = videoInfoList.get(targetPosition).getUrl();
            if (uriString != null) {
                MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
                        .createMediaSource(Uri.parse(uriString));
                // Prepare the player with the source.
                player.prepare(videoSource);
                player.setPlayWhenReady(true);
            }
    
    
        }
    

    Now comes in the second problem get visible Video Surface scrolled list.

      private int getVisibleVideoSurfaceHeight(int playPosition) {
            int at = playPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
    
            View child = getChildAt(at);
            if (child == null) {
                return 0;
            }
    
            int[] location01 = new int[2];
            child.getLocationInWindow(location01);
    
            if (location01[1] < 0) {
                return location01[1] + videoSurfaceDefaultHeight;
            } else {
                return screenDefaultHeight - location01[1];
            }
        }
    

    The complete class code is below

    package com.androidwave.exoplayer.ui;
    
    import android.content.Context;
    import android.graphics.Point;
    import android.net.Uri;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.util.AttributeSet;
    import android.view.Display;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.WindowManager;
    import android.widget.AbsListView;
    import android.widget.FrameLayout;
    import android.widget.ImageView;
    
    import com.androidwave.exoplayer.R;
    import com.androidwave.exoplayer.adapter.VideoRecyclerViewAdapter;
    import com.androidwave.exoplayer.model.VideoInfo;
    import com.androidwave.exoplayer.utils.VideoPlayerConfig;
    import com.google.android.exoplayer2.DefaultLoadControl;
    import com.google.android.exoplayer2.ExoPlaybackException;
    import com.google.android.exoplayer2.ExoPlayerFactory;
    import com.google.android.exoplayer2.LoadControl;
    import com.google.android.exoplayer2.PlaybackParameters;
    import com.google.android.exoplayer2.Player;
    import com.google.android.exoplayer2.SimpleExoPlayer;
    import com.google.android.exoplayer2.Timeline;
    import com.google.android.exoplayer2.source.ExtractorMediaSource;
    import com.google.android.exoplayer2.source.MediaSource;
    import com.google.android.exoplayer2.source.TrackGroupArray;
    import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
    import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
    import com.google.android.exoplayer2.trackselection.TrackSelection;
    import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
    import com.google.android.exoplayer2.trackselection.TrackSelector;
    import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
    import com.google.android.exoplayer2.ui.PlayerView;
    import com.google.android.exoplayer2.upstream.BandwidthMeter;
    import com.google.android.exoplayer2.upstream.DataSource;
    import com.google.android.exoplayer2.upstream.DefaultAllocator;
    import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
    import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
    import com.google.android.exoplayer2.util.Util;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class ExoPlayerRecyclerView extends RecyclerView {
    
        private List<VideoInfo> videoInfoList = new ArrayList<>();
        private int videoSurfaceDefaultHeight = 0;
        private int screenDefaultHeight = 0;
        SimpleExoPlayer player;
        //surface view for playing video
        private PlayerView videoSurfaceView;
        private ImageView mCoverImage;
        private Context appContext;
    
    
        /**
         * the position of playing video
         */
        private int playPosition = -1;
    
        private boolean addedVideo = false;
        private View rowParent;
    
        /**
         * {@inheritDoc}
         *
         * @param context
         */
        public ExoPlayerRecyclerView(Context context) {
            super(context);
            initialize(context);
        }
    
        /**
         * {@inheritDoc}
         *
         * @param context
         * @param attrs
         */
        public ExoPlayerRecyclerView(Context context,
                                     AttributeSet attrs) {
            super(context, attrs);
            initialize(context);
        }
    
        /**
         * {@inheritDoc}
         *
         * @param context
         * @param attrs
         * @param defStyleAttr
         */
        public ExoPlayerRecyclerView(Context context,
                                     AttributeSet attrs,
                                     int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initialize(context);
        }
    
        public void setVideoInfoList(List<VideoInfo> videoInfoList) {
            this.videoInfoList = videoInfoList;
    
        }
    
    
        /**
         * prepare for video play
         */
        //remove the player from the row
        private void removeVideoView(PlayerView videoView) {
    
            ViewGroup parent = (ViewGroup) videoView.getParent();
            if (parent == null) {
                return;
            }
    
            int index = parent.indexOfChild(videoView);
            if (index >= 0) {
                parent.removeViewAt(index);
                addedVideo = false;
            }
    
        }
    
        //play the video in the row
        public void playVideo() {
            int startPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
            int endPosition = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
    
            if (endPosition - startPosition > 1) {
                endPosition = startPosition + 1;
            }
    
            if (startPosition < 0 || endPosition < 0) {
                return;
            }
    
            int targetPosition;
            if (startPosition != endPosition) {
                int startPositionVideoHeight = getVisibleVideoSurfaceHeight(startPosition);
                int endPositionVideoHeight = getVisibleVideoSurfaceHeight(endPosition);
                targetPosition = startPositionVideoHeight > endPositionVideoHeight ? startPosition : endPosition;
            } else {
                targetPosition = startPosition;
            }
    
            if (targetPosition < 0 || targetPosition == playPosition) {
                return;
            }
            playPosition = targetPosition;
            if (videoSurfaceView == null) {
                return;
            }
            videoSurfaceView.setVisibility(INVISIBLE);
            removeVideoView(videoSurfaceView);
    
            // get target View targetPosition in RecyclerView
            int at = targetPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
    
            View child = getChildAt(at);
            if (child == null) {
                return;
            }
    
            VideoRecyclerViewAdapter.ViewHolder holder
                    = (VideoRecyclerViewAdapter.ViewHolder) child.getTag();
            if (holder == null) {
                playPosition = -1;
                return;
            }
            mCoverImage = holder.mCover;
            FrameLayout frameLayout = holder.itemView.findViewById(R.id.video_layout);
            frameLayout.addView(videoSurfaceView);
            addedVideo = true;
            rowParent = holder.itemView;
            videoSurfaceView.requestFocus();
            // Bind the player to the view.
            videoSurfaceView.setPlayer(player);
    
            // Measures bandwidth during playback. Can be null if not required.
            DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
            // Produces DataSource instances through which media data is loaded.
    
            DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(appContext,
                    Util.getUserAgent(appContext, "android_wave_list"), defaultBandwidthMeter);
            // This is the MediaSource representing the media to be played.
            String uriString = videoInfoList.get(targetPosition).getUrl();
            if (uriString != null) {
                MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
                        .createMediaSource(Uri.parse(uriString));
                // Prepare the player with the source.
                player.prepare(videoSource);
                player.setPlayWhenReady(true);
            }
    
    
        }
    
        private int getVisibleVideoSurfaceHeight(int playPosition) {
            int at = playPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
    
            View child = getChildAt(at);
            if (child == null) {
                return 0;
            }
    
            int[] location01 = new int[2];
            child.getLocationInWindow(location01);
    
            if (location01[1] < 0) {
                return location01[1] + videoSurfaceDefaultHeight;
            } else {
                return screenDefaultHeight - location01[1];
            }
        }
    
    
        private void initialize(Context context) {
    
            appContext = context.getApplicationContext();
            Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            Point point = new Point();
            display.getSize(point);
            videoSurfaceDefaultHeight = point.x;
    
            screenDefaultHeight = point.y;
            videoSurfaceView = new PlayerView(appContext);
            videoSurfaceView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_ZOOM);
    
            BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
            TrackSelection.Factory videoTrackSelectionFactory =
                    new AdaptiveTrackSelection.Factory(bandwidthMeter);
            TrackSelector trackSelector =
                    new DefaultTrackSelector(videoTrackSelectionFactory);
            LoadControl loadControl = new DefaultLoadControl(
                    new DefaultAllocator(true, 16),
                    VideoPlayerConfig.MIN_BUFFER_DURATION,
                    VideoPlayerConfig.MAX_BUFFER_DURATION,
                    VideoPlayerConfig.MIN_PLAYBACK_START_BUFFER,
                    VideoPlayerConfig.MIN_PLAYBACK_RESUME_BUFFER, -1, true);
    
            // 2. Create the player
            player = ExoPlayerFactory.newSimpleInstance(appContext, trackSelector, loadControl);
            // Bind the player to the view.
            videoSurfaceView.setUseController(false);
            videoSurfaceView.setPlayer(player);
    
            addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    if (newState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
                        playVideo();
                    }
                }
    
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                }
            });
    
            addOnChildAttachStateChangeListener(new OnChildAttachStateChangeListener() {
                @Override
                public void onChildViewAttachedToWindow(View view) {
    
                }
    
                @Override
                public void onChildViewDetachedFromWindow(View view) {
                    if (addedVideo && rowParent != null && rowParent.equals(view)) {
                        removeVideoView(videoSurfaceView);
                        playPosition = -1;
                        videoSurfaceView.setVisibility(INVISIBLE);
                    }
    
                }
            });
            player.addListener(new Player.EventListener() {
                @Override
                public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
    
                }
    
                @Override
                public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
    
                }
    
                @Override
                public void onLoadingChanged(boolean isLoading) {
    
                }
    
                @Override
                public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                    switch (playbackState) {
    
                        case Player.STATE_BUFFERING:
                            //   videoSurfaceView.setAlpha(0.5f);
                            break;
                        case Player.STATE_ENDED:
                            player.seekTo(0);
                            break;
                        case Player.STATE_IDLE:
    
                            break;
                        case Player.STATE_READY:
                            videoSurfaceView.setVisibility(VISIBLE);
                            videoSurfaceView.setAlpha(1);
                            mCoverImage.setVisibility(GONE);
    
                            break;
                        default:
                            break;
                    }
                }
    
                @Override
                public void onRepeatModeChanged(int repeatMode) {
    
                }
    
                @Override
                public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
    
                }
    
                @Override
                public void onPlayerError(ExoPlaybackException error) {
    
                }
    
                @Override
                public void onPositionDiscontinuity(int reason) {
    
                }
    
                @Override
                public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
    
                }
    
                @Override
                public void onSeekProcessed() {
    
                }
            });
        }
    
        public void onPausePlayer() {
            if (videoSurfaceView != null) {
                removeVideoView(videoSurfaceView);
                player.release();
                videoSurfaceView = null;
            }
        }
    
        public void onRestartPlayer() {
            if (videoSurfaceView == null) {
                playPosition = -1;
                playVideo();
            }
        }
    
        /**
         * release memory
         */
        public void onRelease() {
    
            if (player != null) {
                player.release();
                player = null;
            }
    
            rowParent = null;
        }
    
    
    }
    
    

    Now ExoPlayerRecyclerView.java component is ready to use. Now I will explain how to use this component.

    Create a VideoInfo.java model class

    public class VideoInfo {
        private int mId;
        private String mTitle;
        private String mUrl;
        private String mCoverUrl;
        private String mUserHandle;
    
        public String getUserHandle() {
            return mUserHandle;
        }
    
        public void setUserHandle(String mUserHandle) {
            this.mUserHandle = mUserHandle;
        }
    
        public int getId() {
            return mId;
        }
    
        public void setId(int mId) {
            this.mId = mId;
        }
    
        public String getTitle() {
            return mTitle;
        }
    
        public void setTitle(String mTitle) {
            this.mTitle = mTitle;
        }
    
        public String getUrl() {
            return mUrl;
        }
    
        public void setUrl(String mUrl) {
            this.mUrl = mUrl;
        }
    
        public String getCoverUrl() {
            return mCoverUrl;
        }
    
        public void setCoverUrl(String mCoverUrl) {
            this.mCoverUrl = mCoverUrl;
        }
    } 
    

    Create a RecyclerView adapter and bind views with holder

    package com.androidwave.exoplayer.adapter;
    
    import android.support.annotation.NonNull;
    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.FrameLayout;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import com.androidwave.exoplayer.R;
    import com.androidwave.exoplayer.model.VideoInfo;
    import com.androidwave.exoplayer.ui.BaseViewHolder;
    import com.bumptech.glide.Glide;
    import com.bumptech.glide.request.RequestOptions;
    
    import java.util.List;
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    import butterknife.OnClick;
    
    public class VideoRecyclerViewAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    
        public static final int VIEW_TYPE_EMPTY = 0;
        public static final int VIEW_TYPE_NORMAL = 1;
    
        private List<VideoInfo> mInfoList;
    
        public VideoRecyclerViewAdapter(List<VideoInfo> infoList) {
            mInfoList = infoList;
        }
    
        @NonNull
        @Override
        public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            switch (viewType) {
                case VIEW_TYPE_NORMAL:
                    return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false));
                case VIEW_TYPE_EMPTY:
                    return new EmptyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_empty_view, parent, false));
                default:
                    return null;
            }
        }
    
        @Override
        public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
            holder.onBind(position);
        }
    
    
        @Override
        public int getItemViewType(int position) {
            if (mInfoList != null && mInfoList.size() > 0) {
                return VIEW_TYPE_NORMAL;
            } else {
                return VIEW_TYPE_EMPTY;
            }
        }
    
        @Override
        public int getItemCount() {
            if (mInfoList != null && mInfoList.size() > 0) {
                return mInfoList.size();
            } else {
                return 1;
            }
        }
    
    
    
        public void onRelease() {
            if (mInfoList != null) {
                mInfoList.clear();
                mInfoList = null;
            }
        }
    
        public class ViewHolder extends BaseViewHolder {
            @BindView(R.id.textViewTitle)
            TextView textViewTitle;
            @BindView(R.id.userHandle)
            TextView userHandle;
            @BindView(R.id.video_layout)
            public FrameLayout videoLayout;
            @BindView(R.id.cover)
            public ImageView mCover;
            public final View parent;
    
    
            public ViewHolder(View itemView) {
                super(itemView);
                ButterKnife.bind(this, itemView);
                parent = itemView;
            }
    
            protected void clear() {
    
            }
    
            public void onBind(int position) {
                super.onBind(position);
                parent.setTag(this);
                VideoInfo videoInfo = mInfoList.get(position);
                textViewTitle.setText(videoInfo.getTitle());
                userHandle.setText(videoInfo.getUserHandle());
                Glide.with(itemView.getContext())
                        .load(videoInfo.getCoverUrl()).apply(new RequestOptions().optionalCenterCrop())
                        .into(mCover);
            }
        }
    
        public class EmptyViewHolder extends BaseViewHolder {
    
            @BindView(R.id.btn_retry)
            Button retryButton;
    
            @BindView(R.id.tv_message)
            TextView messageTextView;
    
            public EmptyViewHolder(View itemView) {
                super(itemView);
                ButterKnife.bind(this, itemView);
                itemView.setVisibility(View.GONE);
            }
    
            @Override
            protected void clear() {
    
            }
    
            @OnClick(R.id.btn_retry)
            void onRetryClick() {
    
            }
        }
    }
    
    

    Now prepare video array list

       
      private void prepareVideoList() {
            VideoInfo videoInfo = new VideoInfo();
            videoInfo.setId(1);
            videoInfo.setUserHandle("@h.pandya");
            videoInfo.setTitle("Do you think the concept of marriage will no longer exist in the future?");
            videoInfo.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-1.png");
            videoInfo.setUrl("https://androidwave.com/media/androidwave-video-1.mp4");
    
            VideoInfo videoInfo2 = new VideoInfo();
            videoInfo2.setId(2);
            videoInfo2.setUserHandle("@hardik.patel");
            videoInfo2.setTitle("If my future husband doesn't cook food as good as my mother should I scold him?");
            videoInfo2.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-2.png");
            videoInfo2.setUrl("https://androidwave.com/media/androidwave-video-2.mp4");
    
            VideoInfo videoInfo3 = new VideoInfo();
            videoInfo3.setId(3);
            videoInfo3.setUserHandle("@arun.gandhi");
            videoInfo3.setTitle("Give your opinion about the Ayodhya temple controversy.");
            videoInfo3.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-3.png");
            videoInfo3.setUrl("https://androidwave.com/media/androidwave-video-3.mp4");
    
            VideoInfo videoInfo4 = new VideoInfo();
            videoInfo4.setId(4);
            videoInfo4.setUserHandle("@sachin.patel");
            videoInfo4.setTitle("When did kama founders find sex offensive to Indian traditions");
            videoInfo4.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-4.png");
            videoInfo4.setUrl("https://androidwave.com/media/androidwave-video-6.mp4");
    
            VideoInfo videoInfo5 = new VideoInfo();
            videoInfo5.setId(5);
            videoInfo5.setUserHandle("@monika.sharma");
            videoInfo5.setTitle("When did you last cry in front of someone?");
            videoInfo5.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-5.png");
            videoInfo5.setUrl("https://androidwave.com/media/androidwave-video-5.mp4");
    
            videoInfoList.add(videoInfo);
            videoInfoList.add(videoInfo2);
            videoInfoList.add(videoInfo3);
            videoInfoList.add(videoInfo4);
            videoInfoList.add(videoInfo5);
            videoInfoList.add(videoInfo);
            videoInfoList.add(videoInfo2);
            videoInfoList.add(videoInfo3);
            videoInfoList.add(videoInfo4);
            videoInfoList.add(videoInfo5);
    
        }
    

    Finally main actvity looks like

    package com.androidwave.exoplayer;
    
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.DefaultItemAnimator;
    import android.support.v7.widget.LinearLayoutManager;
    
    import com.androidwave.exoplayer.adapter.VideoRecyclerViewAdapter;
    import com.androidwave.exoplayer.model.VideoInfo;
    import com.androidwave.exoplayer.ui.ExoPlayerRecyclerView;
    import com.androidwave.exoplayer.utils.DividerItemDecoration;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    
    import static android.widget.LinearLayout.VERTICAL;
    
    public class MainActivity extends AppCompatActivity {
    
        @BindView(R.id.recyclerViewFeed)
        ExoPlayerRecyclerView recyclerViewFeed;
    
        private List<VideoInfo> videoInfoList = new ArrayList<>();
        private VideoRecyclerViewAdapter mAdapter;
        private boolean firstTime = true;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
            prepareVideoList();
            recyclerViewFeed.setVideoInfoList(videoInfoList);
            mAdapter = new VideoRecyclerViewAdapter(videoInfoList);
            recyclerViewFeed.setLayoutManager(new LinearLayoutManager(this, VERTICAL, false));
            Drawable dividerDrawable = ContextCompat.getDrawable(this, R.drawable.divider_drawable);
            recyclerViewFeed.addItemDecoration(new DividerItemDecoration(dividerDrawable));
            recyclerViewFeed.setItemAnimator(new DefaultItemAnimator());
            recyclerViewFeed.setAdapter(mAdapter);
    
            if (firstTime) {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        recyclerViewFeed.playVideo();
                    }
                });
                firstTime = false;
            }
    
        }
    
        private void prepareVideoList() {
            VideoInfo videoInfo = new VideoInfo();
            videoInfo.setId(1);
            videoInfo.setUserHandle("@h.pandya");
            videoInfo.setTitle("Do you think the concept of marriage will no longer exist in the future?");
            videoInfo.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-1.png");
            videoInfo.setUrl("https://androidwave.com/media/androidwave-video-1.mp4");
    
            VideoInfo videoInfo2 = new VideoInfo();
            videoInfo2.setId(2);
            videoInfo2.setUserHandle("@hardik.patel");
            videoInfo2.setTitle("If my future husband doesn't cook food as good as my mother should I scold him?");
            videoInfo2.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-2.png");
            videoInfo2.setUrl("https://androidwave.com/media/androidwave-video-2.mp4");
    
            VideoInfo videoInfo3 = new VideoInfo();
            videoInfo3.setId(3);
            videoInfo3.setUserHandle("@arun.gandhi");
            videoInfo3.setTitle("Give your opinion about the Ayodhya temple controversy.");
            videoInfo3.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-3.png");
            videoInfo3.setUrl("https://androidwave.com/media/androidwave-video-3.mp4");
    
            VideoInfo videoInfo4 = new VideoInfo();
            videoInfo4.setId(4);
            videoInfo4.setUserHandle("@sachin.patel");
            videoInfo4.setTitle("When did kama founders find sex offensive to Indian traditions");
            videoInfo4.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-4.png");
            videoInfo4.setUrl("https://androidwave.com/media/androidwave-video-6.mp4");
    
            VideoInfo videoInfo5 = new VideoInfo();
            videoInfo5.setId(5);
            videoInfo5.setUserHandle("@monika.sharma");
            videoInfo5.setTitle("When did you last cry in front of someone?");
            videoInfo5.setCoverUrl("https://androidwave.com/media/images/exo-player-in-recyclerview-in-android-5.png");
            videoInfo5.setUrl("https://androidwave.com/media/androidwave-video-5.mp4");
    
            videoInfoList.add(videoInfo);
            videoInfoList.add(videoInfo2);
            videoInfoList.add(videoInfo3);
            videoInfoList.add(videoInfo4);
            videoInfoList.add(videoInfo5);
            videoInfoList.add(videoInfo);
            videoInfoList.add(videoInfo2);
            videoInfoList.add(videoInfo3);
            videoInfoList.add(videoInfo4);
            videoInfoList.add(videoInfo5);
    
        }
    
        @Override
        protected void onPause() {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    recyclerViewFeed.onPausePlayer();
                }
            });
            super.onPause();
        }
    
        @Override
        protected void onResume() {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    recyclerViewFeed.onRestartPlayer();
                }
            });
            super.onResume();
        }
    
        @Override
        protected void onDestroy() {
            if(recyclerViewFeed!=null)
            recyclerViewFeed.onRelease();
            super.onDestroy();
        }
    }
    
    
    Download Sample Project- ExoPlayer in RecyclerView in Android

     
    If you have any query, feel free to connect us.