VideoView and MediaPlayer seekTo always starts from beginning - android

I have some problem with seeking video played in VideoView and resuming it.
Here's some part of my code:
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
#Override
public void onSeekComplete(MediaPlayer mp) {
Log.d("V", "onSeekComplete1 " + videoView.getCurrentPosition());
videoView.start();
Log.d("V", "onSeekComplete1 " + videoView.getCurrentPosition());
}
});
}
});
videoView.setVideoURI('some local uri');
At some point I'm pausing video using:
videoView.pause();
After button click I'm seeking video to certain time, eg. 10 seconds (10 000 ms).
#OnClick(R2.id.ivMove)
void clickMove() {
videoView.seekTo(10000);
}
After that in log I see:
onSeekComplete1 10000
onSeekComplete2 0
So after calling videoView.start() it is starting video from beginning!
But when I call start() without seeking video (eg. one button calls pause() and second calls start() then video is playing correctly - from the moment when it was paused, not from beginning.
Could you tell me what I'm doing wrong?

The problem was caused by MediaPlayer - it is seeking to closest keyframe of the video and it turns out that my testing video has keyframes every ~30 seconds.
I changed to ExoPlayer https://github.com/google/ExoPlayer - it can seek to exact time.

There is a new overload for the MediaPlayer seekTo method. It has a second int parameter, in which you can pass a SEEK_CLOSEST constant. According to Google, "This mode is used with seekTo(long, int) to move media position to a frame (not necessarily a key frame) associated with a data source that is located closest to or at the given time." In testing my own app, it solves the problem for API level >= 26. I'm not sure if there are any good options prior to API level 26.

Try videoView.resume() instead of start()
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
#Override
public void onSeekComplete(MediaPlayer mp) {
Log.d("V", "onSeekComplete1 " + videoView.getCurrentPosition());
videoView.resume();
Log.d("V", "onSeekComplete1 " + videoView.getCurrentPosition());
}
});
}
});
videoView.setVideoURI('some local uri');

Try this solution. It works like charm....
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
#Override
public void onSeekComplete(MediaPlayer mp) {
mp.start();
}
});
}
});

Related

VideoView seekTo 0 instead of specific position

I'm trying to start video from specific position but VideoView has strange behave. When I run code like that
videoView.seekTo(2000)
int current = videoView.getCurrentPosition()
Log.e("Current Time", String.valueOf(current))
Log gives me value 0. It should give 2000 because this is current position. Even If I implement onPreparedListener it doesn't worked (but in different way). It display proper value (2000) but video still is not seek.
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp)
{
videoView.getDuration();
videoView.seekTo(2000);
Log.e("Current: ", String.valueOf(videoView.getCurrentPosition()));
}
});
How to fight this ? If I will build MediaPlayer + SurfaceView it will helps or will behave same as VideoView ?
Actually, the thing is,VideoView.seekTo() is a wrapper around MediaPlayer.seekTo(). This function returns almost immediately even though the actual seeking is still being performed. Therefore you want to wait for seeking to complete via MediaPlayer.OnSeekCompleteListener.
However, the standard VideoView does not support OnSeekCompleteListener.
But you can copy and locally customize the VideoView class to add this support yourself.
Or, You could try this
mVideoView.setOnPreparedListener(new MediaPlayer .OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setOnSeekCompleteListener(new OnSeekCompleteListener() {
#Override
public void onSeekComplete(MediaPlayer mp) {
Log.e("Current: ", String.valueOf(videoView.getCurrentPosition()));
}
});
}
});
videoView.seekTo(2000); //or wherever the call is to be made
Hope this should help.

Android: How to detect when Audio stops playing

I am having a problem with MediaPlayer class' setOnCompletionListener Method. in my project I have a button, which text is Play, and when I press on it, player starts playing and it's text is changed to Pause. I want to change button's text to Play again once the track has finished playing. I used this code, which doesn't work for me.
//in onCreate() method:
player = MediaPlayer.create(getApplicationContext(), tracks[0]);
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
trackBtn.setText("Play");
}
});
Here is how I have it, if you have any more question please let me know:
player.setOnCompletionListener(this);
IntroClip.execute(player);
}
#Override
public void onCompletion(MediaPlayer mp){
trackBtn.setText("Play");
}

Playing sounds in Android in certain order

In an Android app I am using MediaPlayer to play sound files.
This is just for personal use and will not be published.
I have several references to the sound files:
MediaPlayer dooropen = MediaPlayer.create(MainActivity.this, R.raw.dooropen);
MediaPlayer doorclose = MediaPlayer.create(MainActivity.this, R.raw.doorclose);
//...
For example the length of the dooropen sound clip is 2 seconds so after I play it I sleep for 2.5 seconds and then play the doorclose sound clip, like so
dooropen.start();
try{ Thread.sleep(2500); }catch(InterruptedException e){ }
doorclose.start();
The issue I am having is some of my sound files are not playing in the order I have them in.
There does not seem to be any reason why certain sound files do not play, because if I play them at the top of my onCreate() procedure they all play, it is only when I try and play them in a certain order.
You should implement the setOnCompletionListener() of the mediaplayer to get a callback when playback has completed and then load another audio file that needs to start playing.
See MediaPlayer Documentation about the mediaplayer state.
Yes you can use MediaPlayer along with oncompletionListener or you may try reseting the mediaplayer after one audio is completed. example code here. You may also use session id to keep track of which file was playing and which to start now.
mPlayer = new MediaPlayer();
//set other attributes here
mPlayer.setAudioSessionId(1);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//check which audio session was playing and set new datasource and session
mPlayer.reset();
//set other data source here and different session id
}
});
Hope it solves your problem.
If you want to play sound in order, try this:
mp1.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp2.start();
}
});
mp2.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp3.start();
}
});
mp3.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp1.start();
}
});

Android play multiple mp4 files in succession

I am developing a DASH client for Android and am testing the playback multiple video segments in mp4 format on Android. Therefore I tried two approaches so far:
using VideoView:
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
videoView.setVideoURI(uri);
videoView.requestFocus();
videoView.setVisibility(View.VISIBLE);
videoView.start();
}
});
using TextureView:
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
try {
mMediaPlayer.setSurface(surface);
mMediaPlayer.reset();
mMediaPlayer.setDataSource(file.getAbsolutePath());
mMediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
});
Okay both work but have a little lag when switching to the next file. What can cause that? Am I doing something wrong and can improve the code? I read about using the MediaExtractor and MediaCodec APIs for better playback of multiple videos which were also improved for DASH compatibility with Android verisons 4.3 and 4.4 but I haven't understood yet how to use them to play video and audio on a surface. I can only find sources on how to us them in order to play video or audio.
I hope somebody can help me to play multiple video segments in succession seamlessly.

android MediaPlayer Looping

I am trying to play a looping Ogg file, I tried enabling setLooping(true) but that had no effect so I tried onCompletionListener and that's not working either, could someone clarify what I am doing wrong?
musicPlayer = MediaPlayer.create(mContext, R.raw.overworld);
musicPlayer.setVolume(musicVolume, musicVolume);
// musicPlayer.setLooping(true);
musicPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
musicPlayer.stop();
musicPlayer.seekTo(0);
musicPlayer.start();
Log.d("Sound Manager", "Song Completed");
}
});
Following is my play function,
public void playSong(int id) {
try {
stopSong();
musicPlayer = MediaPlayer.create(mContext, id);
musicPlayer.start();
} catch(Exception e) {
// Ignored
}
}
It's known that MediaPlayer is having problems with ogg files.
You could preferrably switch to another file format.
The other thing is, I would go on trying with setLooping(boolean) as it's most likely using the same scheme and its much more clearly.
Calling seekTo() if the MediaPlayer Object is stopped causes the MediaPlayer to be in an invalid state. You can call pause() instead but I wouldn't call any of these method, why not just seeking? I would guess if you remove the musicPlayer.stop() it will work.
remove ....
musicPlayer.stop();
from
onCompletion(MediaPlayer mp)
onCompletionListener() is not called if your MediaPlayer is set to looping, BUT if you don't have it set to looping, you can always just use a completion listener like so
#Override
public void onCompletion(MediaPlayer mp) {
if(!mp.isPlaying()) {
mp.start();
}
mp.seekTo(0);
}
You also shouldn't call stop() because that stops playback completely, and it doesn't make sense to seek in a video/song that you are not playing.

Categories

Resources