I want to play Videos in my RecyclerView Items, kind of like Instagram. There is only one Item expanded at a time so the Videos don't have to be played at the same time.
Im currently using the ExoPlayer. I have a PlayerView inside my item for the RecyclerView.
The problem is, with the Player I have bad performance which is very bad when scrolling and expanding. The Performany is already bad with just having the Player in the item without loading and playing a Video but it gets even worse with loading it.
I have tried VideoView too but it doesn't seem to make a big difference.
To achieve a better performance I already do:
recyclerView.setHasFixedSize(true);
recyclerView.setItemViewCacheSize(10);
recyclerView.setDrawingCacheEnabled(true);
recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
adapter.hasStableIds();
This helps a little bit but its doesn't solve the performance problem.
Any Idea what the problem can be? I appreciate and thoughts.
EDIT:
this is the method I setup the ExoPlayer:
public void showTutuorItems(Context context, Boolean show, String resource) {
if (show) {
seperator.setVisibility(View.VISIBLE);
lytTutor.setVisibility(View.VISIBLE);
playerView = itemView.findViewById(R.id.exoPlayer);
playerView.setUseController(false);
playerView = itemView.findViewById(R.id.exoPlayer);
playerView.setUseController(false);
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(context),
new DefaultTrackSelector(), new DefaultLoadControl());
playerView.setPlayer(player);
player.setPlayWhenReady(true);
player.seekTo(0, 0);
player.setRepeatMode(Player.REPEAT_MODE_ALL);
player.setVolume(0);
Uri uri = Uri.parse(resource);
MediaSource mediaSource = buildMediaSource(uri);
player.prepare(mediaSource, true, false);
player.addListener(new Player.EventListener() {
//...
}
} else {
seperator.setVisibility(View.GONE);
lytTutor.setVisibility(View.GONE);
}
}
private MediaSource buildMediaSource(Uri uri) {
return new ExtractorMediaSource.Factory(
new DefaultHttpDataSourceFactory("exoplayer-codelab")).
createMediaSource(uri);
}
and this is in my OnCreateViewHolder to call this method:
if (workout.getCurrentExercsise().getTutor() != null) {
holder.showTutuorItems(activity, true, workout.getCurrentExercsise().getTutor().getItems().get(0).getResource());
} else {
holder.showTutuorItems(activity, false, null);
}
In my OnBindViewHolder is some UI stuff and handling the expand/collapse function. This shouldn't cause the problem because without the ExoPlayer it works just fine.
Related
In my app there is a recyclerview that with an exoplayer. When I leave my app or change the screen, the video keeps playing. I need to make it pause when I leave the screen.
I tried using the onViewRecycled method but the video is only paused when I return to the screen where the video is playing.
#Override
public void onViewRecycled(#NonNull MyViewHolder holder) {
super.onViewRecycled(holder);
if (holder.simpleExoPlayer != null) {
holder.positionExo = holder.simpleExoPlayer.getCurrentPosition();
holder.simpleExoPlayer.setPlayWhenReady(false);
}
}
My Adapter:
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
//...
holder.simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(context);
// Bind the player to the view.
holder.videoCnt.setPlayer(holder.simpleExoPlayer);
holder.videoUri = Uri.parse(content.getVideo());
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, context.getString( R.string.app_name)));
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(holder.videoUri);
// Prepare the player with the source.
holder.simpleExoPlayer.prepare(videoSource);
//...
}
How to pause the video correctly?
I am currently developing a live and movie player application. I chose ExoPlayer version 2 to play the movie and I do not know much about it. I want to let the user choose the quality of a movie on the player screen, for example, 720p or 1080p or etc.
But I do not know how to get a list of existing qualities and show them to the user.
and the below code is my implementation of SimpleExoPlayer :
private void initPlayer(String path){
Handler handler = new Handler();
// 1. Create a default TrackSelector
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
// 2. Create a default LoadControl
LoadControl loadControl = new DefaultLoadControl();
// 3. Create the player
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
SimpleExoPlayerView playerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
playerView.setPlayer(player);
playerView.setKeepScreenOn(true);
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayer"));
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new HlsMediaSource(Uri.parse(path),
dataSourceFactory,handler, null);
// Prepare the player with the source.
player.addListener(this);
player.prepare(videoSource);
playerView.requestFocus();
player.setPlayWhenReady(true); // to play video when ready. Use false to pause a video
}
// ExoPlayer Listener Methods :
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
#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 ExoPlayer.STATE_BUFFERING:
//You can use progress dialog to show user that video is preparing or buffering so please wait
progressBar.setVisibility(View.VISIBLE);
break;
case ExoPlayer.STATE_IDLE:
//idle state
break;
case ExoPlayer.STATE_READY:
// dismiss your dialog here because our video is ready to play now
progressBar.setVisibility(GONE);
//Toast.makeText(getApplicationContext(),String.valueOf(player.getCurrentTrackSelections().get(0).getSelectedFormat().bitrate),Toast.LENGTH_SHORT).show();
break;
case ExoPlayer.STATE_ENDED:
// do your processing after ending of video
break;
}
}
#Override
public void onPlayerError(ExoPlaybackException error) {
// show user that something went wrong. it can be a dialog
}
#Override
public void onPositionDiscontinuity() {
}
please help to solve this issue.
thanks a lot.
Everything you'd like to achieve is viewable in the ExoPlayer2 demo app. More specifically the PlayerActivity class.
You can also check out this good article on the topic.
The core points you'll want to look into are around track selection (via the TrackSelector) as well as the TrackSelectionHelper. I'll include the important code samples below which will hopefully be enough to get you going. But ultimately just following something similar in the demo app will get you where you need to be.
You'll hold onto the track selector you init the player with and use that for just about everything.
Below is just a block of code to ideally cover the gist of what you're trying to do since the demo does appear to over-complicate things a hair. Also I haven't run the code, but it's close enough.
// These two could be fields OR passed around
int videoRendererIndex;
TrackGroupArray trackGroups;
// This is the body of the logic for see if there are even video tracks
// It also does some field setting
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
for (int i = 0; i < mappedTrackInfo.length; i++) {
TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(i);
if (trackGroups.length != 0) {
switch (player.getRendererType(i)) {
case C.TRACK_TYPE_VIDEO:
videoRendererIndex = i;
return true;
}
}
}
// This next part is actually about getting the list. It doesn't include
// some additional logic they put in for adaptive tracks (DASH/HLS/SS),
// but you can look at the sample for that (TrackSelectionHelper#buildView())
// Below you'd be building up items in a list. This just does
// views directly, but you could just have a list of track names (with indexes)
for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
TrackGroup group = trackGroups.get(groupIndex);
for (int trackIndex = 0; trackIndex < group.length; trackIndex++) {
if (trackIndex == 0) {
// Beginning of a new set, the demo app adds a divider
}
CheckedTextView trackView = ...; // The TextView to show in the list
// The below points to a util which extracts the quality from the TrackGroup
trackView.setText(DemoUtil.buildTrackName(group.getFormat(trackIndex)));
}
// Assuming you tagged the view with the groupIndex and trackIndex, you
// can build your override with that info.
Pair<Integer, Integer> tag = (Pair<Integer, Integer>) view.getTag();
int groupIndex = tag.first;
int trackIndex = tag.second;
// This is the override you'd use for something that isn't adaptive.
override = new SelectionOverride(FIXED_FACTORY, groupIndex, trackIndex);
// Otherwise they call their helper for adaptives, which roughly does:
int[] tracks = getTracksAdding(override, trackIndex);
TrackSelection.Factory factory = tracks.length == 1 ? FIXED_FACTORY : adaptiveTrackSelectionFactory;
override = new SelectionOverride(factory, groupIndex, tracks);
// Then we actually set our override on the selector to switch the quality/track
selector.setSelectionOverride(rendererIndex, trackGroups, override);
As I mentioned above, this is a slight oversimplification of the process, but the core part is that you're messing around with the TrackSelector, SelectionOverride, and Track/TrackGroups to get this to work.
You could conceivably copy the demo code verbatim and it should work, but I'd highly recommend taking the time to understand what each piece is doing and tailor your solution to your use case.
If I had more time I'd get it to compile and run. But if you can get my sample going then feel free to edit my post.
Hope that helps :)
I avoid the way as above posted. My way is using the DefaultTrackSelector as follows:
trackSelector.setParameters(trackSelector.getParameters()
.withMaxVideoBitrate(bitrate)
.withMaxVideoSize(width, height));
I've tested with HLS videos and it seems to perform in the right way. I get the bitrate, width and height reading from the HlsManifest.
You can copy the sample codes form this link.
ExoPlayer Video Quality Control.
Note : Do not forget to add the exoplayer dependencies in the built.gradle file
implementation 'com.google.android.exoplayer:exoplayer-core:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer:2.16.1'
ExoPlayer is not showing the video. I can listen the audio but video is not playing. I am using the Exoplayer in the Recyclerview.I only can see the black screen and listen to audio.I am not able to track the problem. I am playing the HLS video in the ExoPlayer.
I was also getting same issue few days back, now posting it here so that it can make someone's life easy since this problem appears very often when we use Exoplayer with RecyclerView.
Cause of the issue (in my case):
PlayerView was getting changed every time I came on the screen (due to the presence of RecyclerView)
I handled it by setting the player each time on the PlayerView object inside showLivePlayer() method which is called each time recycler view enabled screen opens to play the video.
public void showLivePlayer(PlayerView playerView, String videoURL, String tokenURL, ProgressBar progressBar){
mPlayerView = playerView;
if(player != null)
mPlayerView.setPlayer(player); //THIS IS THE FIX
mProgressBar = progressBar;
//register event bus
if (!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
shouldAutoPlay = true;
bandwidthMeter = new DefaultBandwidthMeter();
mediaDataSourceFactory = new DefaultDataSourceFactory(mContext,
Util.getUserAgent(mContext, mContext.getString(R.string.app_name)), bandwidthMeter);
window = new Timeline.Window();
getLiveVideoToken(tokenURL, videoURL);
}
my bad was I was using PlayerControlView instead of PlayerView
I have 10 video i need to play, once one is done, the next one starts to play.
I'm using Google's ExoPlayer, I use the example in the DEMO # GitHub.
I can play 1 video but if i try to play the next one, it wont start.
If i try to reInit the player, and the start playing again, it crashes.
private void loadvideo() {
Uri uri = Uri.parse(VIDEO_LIBRARY_URL + currentVideo + ".mp4");
sampleSource = new FrameworkSampleSource(this, uri, null, 2);
// 1. Instantiate the player.
// 2. Construct renderers.
videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
// 3. Inject the renderers through prepare.
player.prepare(videoRenderer, audioRenderer);
// 4. Pass the surface to the video renderer.
surface = surfaceView.getHolder().getSurface();
player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
// 5. Start playback.
player.setPlayWhenReady(true);
player.addListener(new ExoPlayer.Listener() {
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.d(TAG, "onPlayerStateChanged + " + playbackState);
if (playbackState == ExoPlayer.STATE_ENDED) {
currentVideo++;
loadNextVideo();
}
}
#Override
public void onPlayWhenReadyCommitted() {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
});
}
What am i doing wrong?
How can i play videos continuity?
Thanks.
You can reuse the ExoPlayer up until the point that you call release(), and then it should no longer be used.
To change the media that it is currently playing, you essentially need to perform the following steps:
// ...enable autoplay...
player.stop();
player.seekTo(0L);
player.prepare(renderers);
Creating the renderers is a little bit more involved, but that's the flow you should follow and the player should be able to play back to back videos.
I'm using Exoplayer change mp4 video success. I use the example in the DEMO.
1.DEMO project in DemoPlayer.java:
private final RendererBuilder rendererBuilder;
//remove final,then modify that:
private RendererBuilder rendererBuilder;
//and add the set method:
public void setRendererBuilder(RendererBuilder rendererBuilder){
this.rendererBuilder = rendererBuilder;
}
//finally,add stop method
public void stop(){
player.stop();
}
2.DEMO project in PlayerActivity.java:
add method:
private void changeVideo(){
player.stop();
player.seekTo(0L);
//you must change your contentUri before invoke getRendererBuilder();
player.setRendererBuilder(getRendererBuilder());
player.prepare();
playerNeedsPrepare = false;
}
remember change param contentUri before invoke changeVideo method.
Use ConcatenatingMediaSource to play files in sequence.
For example, for playing 2 media Uris (firstVideoUri and secondVideoUri), use this code:
MediaSource firstSource =
new ExtractorMediaSource.Factory(...).createMediaSource(firstVideoUri);
MediaSource secondSource =
new ExtractorMediaSource.Factory(...).createMediaSource(secondVideoUri);
ConcatenatingMediaSource concatenatedSource =
new ConcatenatingMediaSource(firstSourceTwice, secondSource);
And then use concatenatedSource to play media files sequentially.
OK, Answering my own question.
on the example, google init the ExoPlayer at OnResume().
i had to re-init for every video like that:
player = ExoPlayer.Factory.newInstance(2, 1000, 5000);
if someone has a better idea, please let me know.
There is another solution, you could refer to ConcatenatingMediaSource to achieve auto play next media.
In Demo App example :
1. Launch ExoPlayer
2. Select Playlists
3. Choose Cats->Dogs
I created an VideoView in my activity, below is the code.
VideoView vvVideos = (VideoView) rootView.findViewById(R.id.videoView);
MediaController mediacontroller = new MediaController(ctx);
mediacontroller.setAnchorView(vvVideos);
Uri video = Uri.parse("android.resource://" + packageName +"/"+R.raw.sample);
vvVideos.setMediaController(mediacontroller);
LayoutParams params=vvVideos.getLayoutParams();
params.height=150;
vvVideos.setLayoutParams(params);
vvVideos.setVideoURI(video);
vvVideos.requestFocus();
vvVideos.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
vvVideos.start();
}
});
Now the video gets started to play when the activity gets created. I want to make my activity as follows
Video should not play when the activity gets open.
It shoud display the starting video image(currently its displaying black color)
It should play only when the user click on the video.
please help me.
Use seekTo( 1 ) to show the first frame.
Ensure the movie is paused and then use seekTo() to show the first frame of the video:
VideoView mVideoView = (VideoView) findViewById( R.id.video_preview );
mVideoView.setVideoURI( yourVideoPath );
mVideoView.seekTo( 1 ); // 1 millisecond (0.001 s) into the clip.
NOTE: We use .seekTo( 1 ) because setting .seekTo( 0 ) did not work on Android 9.
To have it play when clicked on has been answered by #Lingviston in another answer.
Create video thumbnail using this
Bitmap thumb = ThumbnailUtils.createVideoThumbnail("file path/url",
MediaStore.Images.Thumbnails.MINI_KIND);
and set to videoview
BitmapDrawable bitmapDrawable = new BitmapDrawable(thumb);
mVideoView.setBackgroundDrawable(bitmapDrawable);
1) Remove your onPrepareListener. I don't know why your video is starting playing after activity creation but onPrepareListener is called after videoView.start().
2) Add an ImageView widget into you layout on top of VideoView. Then set another onPrepareListener like this:
vvVideos.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
previewImage.setVisibility(View.GONE);
}
});
I've noticed that onPreparedListener fires too early, so you can use
new Handler().postDelay(Runnable, timeInMilis)
to dismiss preview image.
3) Add OnTouchListener with any gesture detection to you VideoView. Here is an example of what I'm using now:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
mGestureDetector = new GestureDetector(this, mGestureListener);
((VideoView) findViewById(R.id.activity_video_videoview)).setOnTouchListener(mTouchListener);
}
private OnTouchListener mTouchListener = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return true;
}
};
private SimpleOnGestureListener mGestureListener = new SimpleOnGestureListener() {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if(mVideoView.isPlaying())
mVideoView.pause();
else
mVideoView.start();
return true;
};
};
It starts/stops playing by a tap.
just seek video to 100 milliseconds it shows thumbnail using seekTo() method
videoView.seekTo(100);
You can do it with Glide 4.x. It will fetch the first frame of your video show it in an ImageView
add to your build.gradle
implementation 'com.github.bumptech.glide:glide:4.x.x'
and in your Class
GlideApp.with(context)
.load("your video URL")
.into(videoImageView);;
Thought I'd share my solution. The seekTo method works great but only for some devices. Here is my work around. I handle this in the onPrepared method for the onPreparedListener but its up to you.
#Override
public void onPrepared(MediaPlayer mp) {
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(uri.getPath());
try {
Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(currentPosition);
videoView.setBackgroundDrawable(new BitmapDrawable(bitmap));
} catch (OutOfMemoryError outOfMemoryError) {
//Not entirely sure if this will ever be thrown but better safe than sorry.
videoView.seekTo(currentPosition);
}
}
Now when you play the video you will need to remove this background image like so:
private void play() {
...
videoView.setBackgroundDrawable(null);
..
}
Enjoy!
I know it's an old question, but I needed the same solution and couldn't find the answer anywhere else so I did the solution and I'm sharing the love here:
I just created a little class for it:
public class LoadFirstVideoFrame implements Runnable {
private static Handler uiHandler = new Handler(Looper.getMainLooper());
private VideoView videoView;
private LoadFirstVideoFrame(VideoView videoView) {
this.videoView = videoView;
videoView.start();
videoView.resume();
uiHandler.post(this);
}
public void stop() {
videoView = null;
uiHandler.removeCallbacks(this);
}
#Override public void run() {
if (videoView == null) return;
if (videoView.isPlaying()) {
videoView.pause();
videoView.seekTo(0);
videoView = null;
} else {
uiHandler.post(this);
}
}
}
it simply asks to start playing and pauses the video back on the first frame as soon as it's actually playing (meaning it loaded the file and it's already rendering it on the SurfaceView).
The important note here is to remember to call stop() on this class so it can properly clean up and not memory leak anything.
I hope it helps.
I Have Created A ImageView For Thumbnail Like This
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:clickable="true"
android:focusable="true">
<VideoView
android:id="#+id/video_view"
android:layout_width="match_parent"
android:layout_height="220dp"/>
<ImageView
android:id="#+id/videoView_thumbnail"
android:layout_width="match_parent"
android:layout_height="220dp"
android:scaleType="centerCrop"/>
</RelativeLayout>
And Add setOnPreparedListener and setOnCompletionListener in Java Like This Way
VideoView videoView = (VideoView) view.findViewById(R.id.video_view);
ImageView thumbnailView=(ImageView)view.findViewById(R.id.videoView_thumbnail);
Glide.with(getApplicationContext()).load(your_Image_Path).into(thumbnailView);
//you can add progress dialog here until video is start playing;
mediaController= new MediaController(getContext());
mediaController.setAnchorView(videoView);
videoView.setMediaController(mediaController);
videoView.setKeepScreenOn(true);
videoView.setVideoPath(your_video_path);
videoView.start(); //call this method for auto playing video
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
thumbnailView.setVisibility(View.GONE);
//you can Hide progress dialog here when video is start playing;
}
});
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
videoView.stopPlayback();
thumbnailView.setVisibility(View.VISIBLE);
}
});
It Works For Me Very Well I Hope Its Usfull For All
very simple !!!
you can use glide library.
first add an imageView on videoView and use the code below:
GlideApp.with(getApplicationContext()).load("empty")
.thumbnail(GlideApp.with(getApplicationContext()).load("videoURL"))
.into(imageView);
this code will download an image, and eventually, that leads to less internet consumption.
You can use a #Joshua Pinter's answer to solve the problem. But I want to give you more suggestion about it. You yourself answer that seekTo(100) works instead of seekTo(1). Neither of the two ways is perfect. That is because seekTo(1) would get a black image and the seekTo(100) may got an exception.
I prefer to do like this:
// calculate the during time of the media
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
long time = mediaPlayer.getDuration();
// use a proper number
mVideoView.seekTo(time/2);
If you don't have the backend server, it may be better. Or, if you had a backend server, you can try it in this way.
The thumbnail is calculate by the server, the client just display the image which the backend response. And when it come to server side, you can do a lot of things.
Which picture is better? What if the picture is black too?
Should the server side generate it? Or should the server side just cache the picture of the media?
If you want to discuss more about the two questions we can discuss them later.
Add this in your xml
`<RelativeLayout
android:layout_width="match_parent"
android:layout_height="#dimen/dimen180"
android:background="#color/color_bg">
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/epPlayer"
android:layout_width="match_parent"
android:visibility="gone"
android:layout_height="match_parent"/>
<FrameLayout
android:id="#+id/flTv"
android:layout_width="match_parent"
android:background="#color/color_bg"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/ivTv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/tv"/>
</FrameLayout>
<ProgressBar
android:id="#+id/pbVideoView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_centerInParent="true"
android:indeterminate="true" />
</RelativeLayout>
`
for kotlin users
declare variable
private var simpleExoPlayer: ExoPlayer? = null
use this
simpleExoPlayer = SimpleExoPlayer.Builder(this).build()
epPlayer.player = simpleExoPlayer
val dataSourceFactory = DefaultDataSourceFactory(
this,
Util.getUserAgent(this, getString(R.string.app_name))
)
val videoSource = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(it1))
simpleExoPlayer!!.prepare(videoSource)
simpleExoPlayer!!.playWhenReady = true
simpleExoPlayer!!.addListener(object : Player.EventListener{
override fun onPlayerStateChanged(
playWhenReady: Boolean,
playbackState: Int
) {
if(playbackState== Player.STATE_READY)
{
pbVideoView.visibility= View.GONE
epPlayer.visibility= View.VISIBLE
flTv.visibility= View.GONE
}
if (playbackState== Player.STATE_BUFFERING)
{
pbVideoView.visibility= View.VISIBLE
}
}
})
I hope it helps.
To make your video stop playing when the activity starts just remove the video.start() method.