How to detect when VideoView starts playing (Android)? - android

Here's the problem, I want to change play button to pause button when the video stream starts playing in videoview but I don't know how to detect that event?

There is a great article about MediaPlayer in here - http://www.malmstein.com/blog/2014/08/09/how-to-use-a-textureview-to-display-a-video-with-custom-media-player-controls/
You can set infoListener on your VideoView
setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
// Here the video starts
return true;
}
return false;
}

I ended up using VideoView.setOnPreparedListener. This was enough to cover my problem (play button drawable change to pause)

accepted answer here is not 100% accurate.
sometimes onprepared is call 3 seconds before first frame is being rendered. i suggest having a callback on that event (MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START)
mMediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mediaPlayer, int i, int i1) {
if (i == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START){
//first frame was bufered - do your stuff here
}
return false;
}
});
see media info documantaion for more callbacks of info/warning:
https://developer.android.com/reference/android/media/MediaPlayer.html#MEDIA_INFO_VIDEO_RENDERING_START

As far as I know, there is no event sent when video start playing in VideoView, but I can think of two options:
Create a version of VideoView by yourself, that sends event in those cases.
Use MediaController (which is default in VideoView)
If you want to follow option one - you can get the source of VideoView from here

isPlaying() can be called to test whether the MediaPlayer object is in the Started
Android MediaPlayer.isPlaying()

Another way to detect if videoview started is using videoView.getCurrentPosition(). getCurrentPosition() returns 0 if streaming not started.
protected Runnable playingCheck = new Runnable() {
public void run() {
while (true) {
if (vw.getCurrentPosition() != 0) {
// do what you want when playing started
break;
} else {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Then call:
new Thread(playingCheck).start();

Please try this :
final Handler h = new Handler();
h.postDelayed( new Runnable() {
public void run() {
if (videoView.getCurrentPosition() != 0) {
((ProgressBar) rootView.findViewById(R.id.pgStreaming)).setVisibility(View.GONE);
} else {
h.postDelayed(this, 250);
}
}
}, 250);

Related

How to stop worker thread in Android

I found and use some method bellow but it is not work for me:
myThread.stop() //it is not safe but I am tried that
myThread.interupt
Here is my program: I wanna play video using Videoview when video finish. If user no choose the next video in 120s then my app will finish.
My video view code:
Uri uri = Uri.parse(filePath);
videoView = findViewById(R.id.videoView);
videoView.setVideoURI(uri);
waitingThread w8 = new waitingThread();
//set params video before play
videoView.setOnPreparedListener(mediaPlayer -> {
PlaybackParams playbackParams = new PlaybackParams();
playbackParams.setSpeed(DeviceConfig.getInstance().getVideoPeed());// 1.25 1.5 2 2.5
mediaPlayer.setPlaybackParams(playbackParams);
// I am tryied using stop thread here
// w8.stop()
// or w8.interrupt();
videoView.start();
});
videoView.setOnErrorListener((mediaPlayer, i, i1) -> {
Log.d(TAG,"Video Error");
//send error message to server
return false;
});
//I call thread when video complete
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
**waiting();** -> w8.start //edited i start thread here
}
});
My thread waiting
private class waitingThread extends Thread{
public void run() {
try {
while (!isInterrupted()) {
timeCount ++;
Thread.sleep(1000);
Log.d(TAG, "Time count : " + timeCount);
if(timeCount == 120){
finish();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//i am try to using this funtion but still not work too.
public void stopping(){
Thread.currentThread().interrupt();
// timeCount = 0;
// Log.d(TAG, "Stopping, reset time :" + timeCount);
}
}
Brief my idea: When video start play, thread waiting will be stopped. When video finish program will waiting a time if no video chose in time to wait program will finish, if any video chose then thread w8 stop.
My problem: when I choose the next video, my thread "w8" still keep running. That is make my app finished while video playing
Plz help me how to fix that problem or any same idea to work are appreciated
You don't want to call interrupt on Thread.currentThread. Thread.currentThread is the thread currently running- it's the thread you're calling the function on. It's not the thread object you just created. Instead it would be this.interrupt(). Or just get rid of the function entirely and call interrupt directly.
Introducing your own boolean variable might help
class waitingThread extends Thread{
boolean stop;
public void run(){
while(!stop){
//your task
}
stop = false; //
}
public void stopping(){
stop= true;
}
}

Hello. I'm making a lyrics app which can also play the music of the lyrics

what I'm trying to do is add 1 button that will play and stop the music. is it possible to loop them like 1st click play then 2nd click stop 3rd click will start from beginning and 4th stops again and so on?
based on my search on google it's something like this? sorry if noob question
public void playtd(View view) {
if(!td.isPlaying()) {
td.start();
}
else if(td.isPlaying()) {
td.pause();
}
}
Try This:
MediaPlayer td;
boolean isPrepared;
public void prepareMediaPlayer(Uri yourTrackUri){
// call this on initialization of your mediaplayer
sMRMediaPlayer = MediaPlayer.create(mContext, uri);
sPrepared = true;
}
public void playtd(View view) {
if (!isPrepared) {
prepareMediaPlayer(Uri yourTrackUri)
}
if(!td.isPlaying()) {
td.start();
else {
// reprepare mediaplayer
td = MediaPlayer.create(Context, uriToUrFile);
isPrepared = true;
}
} else { // stop playing instead of pause, stop will start playing next time u play from beginning
td.stop();
}
void releaseMediaPlayer() {
if (td!= null) {
Log.d(TAG, "MediaPlayer is released.");
td.reset();
td.release();
td= null;
isPrepared = false;
}
}
call releaseMediaPlayer once done with all play and stop stuff (may be on destroy etc.)
initialize mediaplayer by passing track uri to prepareMediaPlayer
add try catch, wherever needed

Playing video in TextureView crash when resuming from onPause

If I pause my activity, on returning I get a crash
Caused by: java.lang.IllegalStateException
at android.media.MediaPlayer.prepareAsync(Native Method)
I want to be able to return to exactly where the video left off and continue from there. I also want it to survive orientations, which it is not doing right now. Thanks for any hint on how to accomplish this. I am not using ExoPlayer because I want to stay with API 14, instead of bumping to API-16 and lose some users.
My setup is Activity -> Fragment {TextureView}. In portrait the fragment is half of the screen; in landscape the fragment is fullscreen.
code snippet
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
surface = new Surface(surfaceTexture);
playVideoNow();
}
private void playVideoNow() {
if(null== textureView || null==surface || null==mCurrVideo) return;
try {
final String url = mCurrVideo.getUrl();
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(getContext(), Uri.parse(url));
mediaPlayer.setSurface(surface);
mediaPlayer.setLooping(false);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer player) {
mediaPlayer.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
playVideoNow() is called from multiple possible places such as onResume on BroadcastReceiver, hence the checks to see if everything is in order. Also the

Android VideoView MediaPlayer OnInfoListener - events not fired

this following source code snippet is given:
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END){
activity.dismissDialog(DialogID.DIALOG_LOADING);
return true;
}
return false;
}
});
}
});
I am streaming HLS streams with Android 3.x+ devices and trying to hide a loading dialog once the buffering is completed.
The video streaming works, but the info events are never fired.
Any ideas?
I know its too late, But posting it for the users still seeking for the solution (This worked for me):
progressDialog.show();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END){
progressDialog.dismiss();
return true;
} else if(what == MediaPlayer.MEDIA_INFO_BUFFERING_START){
progressDialog.show();
}
return false;
}
});
progressDialog.dismiss();
videoView.start();
}
});
You're right, the events are never fired. This is a known HLS bug that I don't think Google will fix.
This applies to the onInfo and the buffering events.
See https://code.google.com/p/android/issues/detail?id=42767 and https://code.google.com/p/googletv-issues/issues/detail?id=2
Sorry!
Not fully sure as to what the OP is asking, but here are some very untimely bits of information.
I wouldn't rely on onPrepared. I find it to be unreliable.
I have found the two most useful pieces of information for HLS streaming through the MediaPlayer are the duration of the video and the progress position of the video. You get both of these by listening to progress updates.
When the duration is greater than zero, you know the video is truly prepared and can be manipulate (scrub). When progress position changes, you know the video is done buffering and has commenced playback. This last item only works when the video is playing of course. The MediaPlayer tends to relay inaccurate information.
These pieces of information are mostly accurate and can usually be relied upon to be "fairly" timely. This timeliness varies from device to device.
onPrepared is called when the MediaPlayer is prepared to start buffering, not when the video is completely buffered. However, it is completely natural to dismiss the loading dialog from within the onPrepared method.
Also MEDIA_INFO_BUFFERING_END is used when MediaPlayer is resuming playback after filling buffers, so I do not think it should be something to use to dismiss the dialog. So this should work:
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
activity.dismissDialog(DialogID.DIALOG_LOADING);
}
});
You can able to set OnPreparedListener on videoView because its your object but if you checkout source of VideoView you will find that mMediaPlayer is its private member so any change that you do from external will not be applied to it.
As per your requirement you need buffering status so you can have thread or handler or some thing so you can update your UI to get buffer status there is one method
int percent = videoView.getBufferPercentage();
if(percent == 100){
// buffering done
}
You no need to go through setOnInfoListener
by overriding setOnPreparedListener method is enough. as in the api show
public void setOnPreparedListener (MediaPlayer.OnPreparedListener l)
Register a callback to be invoked when the media file is loaded and
ready to go.
so, you can dismiss your dialog inside setOnPreparedListener method is enough
like this
vv.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "finish11", Toast.LENGTH_LONG).show();
}
});
}
});
If you want to show loading each time it's buffering (initial time or subsequent buffer underruns) just ensure to show it again:
// at the beginning
show
boolean onInfo(int what, int extra) {
switch (what) {
case MEDIA_INFO_BUFFERING_END:
"hide";
break;
case MEDIA_INFO_BUFFERING_START
"show":
}
}
So this event sequence will do as desired:
- whenever you start (setVideoURI or start): show
- onPrepared: just plug the info listener
- onInfo BUFFERING_END hide (it's playing)
- onInfo BUFFERING_START show (it's buffering again)
- onInfo BUFFERING_END hide (it's playing)
Update:
This is assuming the info events work. Of course.

Android - Buffering in MediaPlayer

I am using MediaPlayer to play a video in my app. The video takes a while to buffer and the videoview is blank for that time.
Is there a way to start the buffering when the user is in the previous screen, so that when he comes to the video playing screen, the video is ready to play?
Thanks
Chris
MediaPlayer lets you register an OnPreparedListener and an OnBufferingUpdateListener.
I've not tried it, but you could try calling MediaPlayer.prepareAsync() while the user is on the previous screen, then call .start() when the user moves to the right screen. Not sure where the media player can live during this process... You might need to do this all within one activity that you dynamically update when the user wants to see the video.
like below:
mp.setOnInfoListener(new OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
loadingDialog.setVisibility(View.VISIBLE);
} else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
loadingDialog.setVisibility(View.GONE);
}
return false;
}
});
mediaPlayer.setOnInfoListener(new OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == 703) {
// Not documented :(
// See http://stackoverflow.com/a/9622717/435605
isBuffering = true;
} else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
isBuffering = false;
}
return false;
}
});

Categories

Resources