I'm using VideoView to play remote videos using HLS
When video is VOD (video on demand - just a remote video file, no live stream) everything works fine.
Problems start when i try to play live streams.
If I'm on the fast network (wifi or 3g/4g) everything works as expected.
If i try to play video over edge network for example, video starts to load, and that's OK.
But if i click back button, whole application just freezes. The weird thing is, that ANR dialog is not shown at all, and the freeze sometimes last more that 20 seconds
Here is the code
...
MediaController mediaController = new MediaController(this);
videoView.setMediaController(mediaController);
videoView.setVideoURI(Uri.parse(Utility.sanitizeUrl(videoUrl)));
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener()
{
#Override
public boolean onError(MediaPlayer mp, int what, int extra)
{
tvError.setVisibility(View.VISIBLE);
videoView.setVisibility(View.GONE);
pbLoading.setVisibility(View.GONE);
return true;
}
});
//we also set an setOnPreparedListener in order to know when the video file is ready for playback
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
{
public void onPrepared(MediaPlayer mediaPlayer)
{
// close the progress bar and play the video
pbLoading.setVisibility(View.GONE);
//if we have a position on savedInstanceState, the video playback should start from here
if(savedVideoPosition > 0)videoView.seekTo(savedVideoPosition);
if (savedVideoPosition == 0)
{
videoView.start();
}
else
{
//if we come from a resumed activity, video playback will be paused
videoView.pause();
}
}
});
...
#Override
protected void onDestroy()
{
super.onDestroy();
videoView.stopPlayback();
}
The only thing i could fine in the logs is this
07-09 10:00:57.665 10499-10499/{package_name_removed} I/Choreographer﹕ Skipped 9565 frames! The application may be doing too much work on its main thread.
Related
I'm trying to build a game which plays some sounds effects on click & at the same time music in the background.
I tried implementing this with two MediaPlayer objects.
The first one, which served for the effects on click works great.
The second one however sometimes logs error 100, sometimes error 38. No sound at all.
Variables
private MediaPlayer mEffects;
private MediaPlayer mpSoundBackground;
Implementation of the sound media player:
mpSoundBackground = MediaPlayer.create(MainActivity.this, R.raw.soundbackground1small);
mpSoundBackground.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
Logger.d("prepared");
musicPrepared = true;
}
});
mpSoundBackground.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Logger.d("error "+what);
return false;
}
});
if (musicPrepared) {
mpSoundBackground.start();
Logger.d("music is prepared");
} else {
Logger.d("music is not prepared");
}
Implementation of the effects Media Player:
stopPlaying();
mEffects= MediaPlayer.create(MainActivity.this, R.raw.soundhit);
mEffects.start();
private void stopPlaying() {
if (mEffects!= null) {
mEffects.stop();
mEffects.release();
mEffects= null;
}
}
Update
To add to the confusion: It does seem to work in emulator
(Genymotion), but does not work on my OnePlus One, running Lollipop
You need to use the setOnPreparedListener method for both players. also if you want to play a sound on clicks consider using SoundPool.
Also in the public void onPrepared(MediaPlayer mp) method, you can use mp.start there is no need for that flag, since you can not know for sure that it is prepared once you reach that prepared flag
I couldn't make the errors go away, until I reconverted my soundfile to MP3.
Now it plays both on device & simulator without any problems.
Moral of this story: if you are running into errors, try a few encodings of the same file (possibly a few file sizes too!), it might be the solution.
If playing a video from the device, the media player knows its exact lenght and fast-forwarding through the video by moving the thumb in the mediacontroller seekbar is seemless.
If playing a streaming video from the internet, the length of the video is unknown and seeking using the thumb causes the video to stop responding.
I want to know how can I disable the thumb until the video is fully buffered? Then show it and enable fast-forwarding.
Following is my video player code:
setContentView(R.layout.layout_fragment_video_fullscreen);
vvVideoFullscreen = (VideoView) findViewById(R.id.vvVideoFullscreen);
rlVideoFullscreen = (RelativeLayout) findViewById(R.id.rlVideoFullscreen);
videoUri = Uri.parse(video.getUrl());
vvVideoFullscreen.setVideoURI(videoUri);
mediaController = new MediaController(this);
mediaController.setMediaPlayer(vvVideoFullscreen);
mediaController.setAnchorView(vvVideoFullscreen);
vvVideoFullscreen.setMediaController(mediaController);
vvVideoFullscreen.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
progressDialog.dismiss();
rlVideoFullscreen.setVisibility(View.VISIBLE);
vvVideoFullscreen.start();
mediaController.show(3000);
}
});
vVideoFullscreen.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
finish();
}
});
vvVideoFullscreen.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (vvVideoFullscreen.isPlaying()) {
vvVideoFullscreen.pause();
mediaController.hide();
} else {
vvVideoFullscreen.start();
mediaController.show();
}
}
return true;
}
}); // End of setOnTouchListener
Have you tried adding an onBufferingUpdateListener() to your mediaplayer?
From the documentation is says:
public abstract void onBufferingUpdate (MediaPlayer mp, int percent)
Called to update status in buffering a media stream received through
progressive HTTP download. The received buffering percentage indicates
how much of the content has been buffered or played. For example a
buffering update of 80 percent when half the content has already been
played indicates that the next 30 percent of the content to play has
been buffered.
So when this callback is invoked with 100%, you know your video is fully buffered.
To disable all playback controls, you can simply only call mediaController.setMediaPlayer(...) when buffering is completed.
If you want to only disable the seek thumb, I suggest to implement your own MediaController.MediaPlayerControlInterface and rout all calls to your MediaPlayer object. Seeking can then be disabled by having the canSeekForward() and canSeekBackward() methods return false and by making the seekTo(int pos) method don't do anything on your MediaPlayer.
Hi in my android application I am using videoview for streaming my videos. I face very unwanted behaviour from my videoview. The scenario is like this. I have activity A and activity B. Activity A has one simple button and on click of that button I am starting activity B which contains videoview and starts playing video as soon as it start my activity. So my observation is like this: Once I start Activity B it will call setVideoURI and start(). there are few callback methods one of them is setOnPreparedListener. when I call start() after some time It is executing setOnPreparedListener and after that it will start playing video. But in between before executing setOnPreparedListener if I come back to Activity A it will block that activity UI for some time. But if I wait till setOnPreparedListener get executes and then come back to Activity A then its working properly. This is not happening with all devices only with google devices like moto g and nexus. But I tried with htc or intel device it is working properly. My code looks like :
VideoView mVideoView =(VideoView)findViewById(R.id.myVideo);
//Creating MediaController
MediaController mediaController= new MediaController(this);
mediaController.setAnchorView(mVideoView);
//specify the location of media file
Uri uri=Uri.parse("http://abcExample.com/playlist.m3u8");
//Setting MediaController and URI, then starting the videoView
mVideoView.setMediaController(mediaController);
mVideoView.setVideoURI(uri);
mVideoView.requestFocus();
mVideoView.start();
mVideoView.setOnErrorListener(new OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i("this is video view sample ... ", "this is video view sample ... this is on error listener ");
return true;
}
});
mVideoView.setOnPreparedListener(new OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
Log.i("this is video view sample ... ", "this is video view sample ... this is on prepared listener ");
}
});
mVideoView.setOnCompletionListener(new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
Log.i("this is video view sample ... ", "this is video view sample ... this is on complete listener ");
}
});
Am I missing something or doing something wrong? Need some help. Thank you.
I'm having the same behaviour with videoview. I was looking for a solution but i didn't find anything. Maybe, It's possible that making a new task fix that issue. I'll try it
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.
Uri uri = Uri.parse(URLPath);
vv.setVideoURI(uri);
vv.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//play next one
}
});
vv.setOnErrorListener(new OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
});
Above code is for playing remote video with VideoView(vv).
It works while on high speed network.
But if low speed network is used such as 3G, playback will fail often, and outside the activity. t seems streaming is slower than user playback. The error code is (1,-1004).
What can I do to replace outside activity with pause and wait for streaming?
You can use Surface View for video streaming...this would work...
This link may help you Click Here