Playing video using textureview in recyclerview

前端 未结 3 1405
清歌不尽
清歌不尽 2020-12-07 16:26

I am trying to implement a list with videos like vine or Instagram app. Where they play video plays when list item is shown or fully visible and video pauses when list item

3条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-07 16:31

    I was able to achieve that by first downloading the videos from url and then playing it with custom player. Here is how i did in case if anyone else needed that:

    1) Get all url's need to be played

    2) Start downloading videos (in queue) from urls in local storage and keep a flag in preferences (that a video is already downloaded or not)

    3) Assign urls to Adapter in which initialize object of video player controller that handles video playbacks

    4) Set addOnScrollListener to check which position/video is currently visible and check if video is already downloaded or not if yes then play it.

    Following is complete code:

    MainActivity

    public class MainActivity extends ActionBarActivity implements IVideoDownloadListener {
    
    private static String TAG = "MainActivity";
    
    private Context context;
    private RecyclerView mRecyclerView;
    private ProgressBar progressBar;
    private VideosAdapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;
    private ArrayList

    VideosAdapter

    public class VideosAdapter extends RecyclerView.Adapter {
    
    private static String TAG = "VideosAdapter";
    
    Context context;
    private ArrayList

    VideosDownloader

    public class VideosDownloader {
    
    private static String TAG = "VideosDownloader";
    
    Context context;
    FileCache fileCache;
    IVideoDownloadListener iVideoDownloadListener;
    
    public VideosDownloader(Context context) {
        this.context = context;
        fileCache = new FileCache(context);
    }
    
    /////////////////////////////////////////////////////////////////
    // Start downloading all videos from given urls
    
    public void startVideosDownloading(final ArrayList

    VideoPlayerController

    public class VideoPlayerController {
    
    private static String TAG = "VideoPlayerController";
    
    Context context;
    FileCache fileCache;
    int currentPositionOfItemToPlay = 0;
    Video currentPlayingVideo;
    
    private Map videos = Collections.synchronizedMap(new WeakHashMap());
    private Map videosSpinner = Collections.synchronizedMap(new WeakHashMap());
    
    public VideoPlayerController(Context context) {
    
        this.context = context;
        fileCache = new FileCache(context);
    }
    
    public void loadVideo(Video video, VideoPlayer videoPlayer, ProgressBar progressBar) {
    
        //Add video to map
        videos.put(video.getIndexPosition(), videoPlayer);
        videosSpinner.put(video.getIndexPosition(), progressBar);
    
        handlePlayBack(video);
    }
    
    //This method would check two things
    //First if video is downloaded or its local path exist
    //Second if the videoplayer of this video is currently showing in the list or visible
    
    public void handlePlayBack(Video video)
    {
        //Check if video is available
        if(isVideoDownloaded(video))
        {
    
            // then check if it is currently at a visible or playable position in the listview
            if(isVideoVisible(video))
            {
                //IF yes then playvideo
                playVideo(video);
            }
        }
    }
    
    private void playVideo(final Video video)
    {
        //Before playing it check if this video is already playing
    
        if(currentPlayingVideo != video)
        {
            //Start playing new url
            if(videos.containsKey(video.getIndexPosition()))
            {
                final VideoPlayer videoPlayer2 = videos.get(video.getIndexPosition());
                String localPath = fileCache.getFile(video.getUrl()).getAbsolutePath();
                if(!videoPlayer2.isLoaded)
                {
                    videoPlayer2.loadVideo(localPath, video);
                    videoPlayer2.setOnVideoPreparedListener(new IVideoPreparedListener() {
                        @Override
                        public void onVideoPrepared(Video mVideo) {
    
                            //Pause current playing video if any
                            if(video.getIndexPosition() == mVideo.getIndexPosition())
                            {
                                if(currentPlayingVideo!=null)
                                {
                                    VideoPlayer videoPlayer1 = videos.get(currentPlayingVideo.getIndexPosition());
                                    videoPlayer1.pausePlay();
                                }
                                videoPlayer2.mp.start();
                                currentPlayingVideo = mVideo;
                            }
    
    
                        }
                    });
                }
                else
                {
                    //Pause current playing video if any
                    if(currentPlayingVideo!=null)
                    {
                        VideoPlayer videoPlayer1 = videos.get(currentPlayingVideo.getIndexPosition());
                        videoPlayer1.pausePlay();
                    }
    
                    boolean isStarted = videoPlayer2.startPlay();
                    {
                        //Log.i(TAG, "Started playing Video Index: " + video.getIndexPosition());
                        //Log.i(TAG, "Started playing Video: " + video.getUrl());
                    }
                    currentPlayingVideo = video;
                }
            }
        }
        else
        {
            //Log.i(TAG, "Already playing Video: " + video.getUrl());
        }
    
    }
    
    private boolean isVideoVisible(Video video) {
    
        //To check if the video is visible in the listview or it is currently at a playable position
        //we need the position of this video in listview and current scroll position of the listview
        int positionOfVideo = Integer.valueOf(video.getIndexPosition());
    
        if(currentPositionOfItemToPlay == positionOfVideo)
            return true;
    
        return false;
    }
    
    private boolean isVideoDownloaded(Video video) {
    
        String isVideoDownloaded = Utils.readPreferences(context, video.getUrl(), "false");
        boolean isVideoAvailable = Boolean.valueOf(isVideoDownloaded);
        if(isVideoAvailable)
        {
            //If video is downloaded then hide its progress
            hideProgressSpinner(video);
            return true;
        }
    
        showProgressSpinner(video);
        return false;
    }
    
    private void showProgressSpinner(Video video) {
        ProgressBar progressBar = videosSpinner.get(video.getIndexPosition());
        if(progressBar!=null)
            progressBar.setVisibility(View.VISIBLE);
    }
    
    private void hideProgressSpinner(Video video) {
    
        ProgressBar progressBar = videosSpinner.get(video.getIndexPosition());
        if(progressBar!=null && progressBar.isShown())
        {
            progressBar.setVisibility(View.GONE);
            Log.i(TAG, "ProgressSpinner Hided Index: " + video.getIndexPosition());
        }
    }
    
    public void setcurrentPositionOfItemToPlay(int mCurrentPositionOfItemToPlay) {
        currentPositionOfItemToPlay = mCurrentPositionOfItemToPlay;
    }
    }
    

    VideoPlayer

    public class VideoPlayer extends TextureView implements TextureView.SurfaceTextureListener {
    
    private static String TAG = "VideoPlayer";
    
    /**This flag determines that if current VideoPlayer object is first item of the list if it is first item of list*/
    boolean isFirstListItem;
    
    boolean isLoaded;
    boolean isMpPrepared;
    
    IVideoPreparedListener iVideoPreparedListener;
    
    Video video;
    String url;
    MediaPlayer mp;
    Surface surface;
    SurfaceTexture s;
    
    public VideoPlayer(Context context) {
        super(context);
    }
    
    public VideoPlayer(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    
    public void loadVideo(String localPath, Video video) {
    
        this.url = localPath;
        this.video = video;
        isLoaded = true;
    
        if (this.isAvailable()) {
            prepareVideo(getSurfaceTexture());
        }
    
        setSurfaceTextureListener(this);
    }
    
    @Override
    public void onSurfaceTextureAvailable(final SurfaceTexture surface, int width, int height) {
        isMpPrepared = false;
        prepareVideo(surface);
    }
    
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    
    }
    
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
    
        if(mp!=null)
        {
            mp.stop();
            mp.reset();
            mp.release();
            mp = null;
        }
    
        return false;
    }
    
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    }
    
    public void prepareVideo(SurfaceTexture t)
    {
    
        this.surface = new Surface(t);
        mp = new MediaPlayer();
        mp.setSurface(this.surface);
    
        try {
            mp.setDataSource(url);
            mp.prepareAsync();
    
            mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                public void onPrepared(MediaPlayer mp) {
                    isMpPrepared = true;
                    mp.setLooping(true);
                    iVideoPreparedListener.onVideoPrepared(video);
                }
    
    
            });
        } catch (IllegalArgumentException e1) {
            e1.printStackTrace();
        } catch (SecurityException e1) {
            e1.printStackTrace();
        } catch (IllegalStateException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        try {
    
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
        try {
    
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    
    }
    
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
    }
    
    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
    }
    
    public boolean startPlay()
    {
        if(mp!=null)
            if(!mp.isPlaying())
            {
                mp.start();
                return true;
            }
    
        return false;
    }
    
    public void pausePlay()
    {
        if(mp!=null)
            mp.pause();
    }
    
    public void stopPlay()
    {
        if(mp!=null)
            mp.stop();
    }
    
    public void changePlayState()
    {
        if(mp!=null)
        {
            if(mp.isPlaying())
                mp.pause();
            else
                mp.start();
        }
    
    }
    
    public void setOnVideoPreparedListener(IVideoPreparedListener iVideoPreparedListener) {
        this.iVideoPreparedListener = iVideoPreparedListener;
    }
    }
    

    IVideoDownloadListener

    public interface IVideoDownloadListener {
    public void onVideoDownloaded(Video video);
    }
    

    IVideoPreparedListener

    public interface IVideoPreparedListener {
    
    public void onVideoPrepared(Video video);
    }
    

提交回复
热议问题