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.
Good afternoon/morning! Hoping someone could help me out with a small problem I'm having. I'm playing a remote .mp3 file using a VideoView and a custom MediaController.
My MediaController looks like this:
public class MyMediaController extends MediaController {
public MyMediaController(Context context) {
super(context);
}
// Do nothing on the overridden hide method so the playback controls will never go away.
#Override
public void hide() {
}
// Override the dispatchKeyEvent function to capture the back KeyEvent and tell the activity to finish.
#Override
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
{
((Activity) getContext()).finish();
}
return super.dispatchKeyEvent(event);
}
}
And my code to attach it to my VideoView looks like this:
VideoView videoView = (VideoView) findViewById(R.id.VideoView);
// Use our own media controller, which inherits from the standard one. Do this to keep
// playback controls from disappearing.
mediaController = new MyMediaController(this);
mediaController.setAnchorView(videoView);
Uri video = Uri.parse(URL);
videoView.setMediaController(mediaController);
videoView.setVideoURI(video);
// Set a handler that will show the playback controls as soon as audio starts.
videoView.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer arg0) {
mediaController.show();
}
});
videoView.start();
The problem I'm having is that when the .mp3 file starts playing, the control bar at the bottom has the "Play" button showing (i.e. triangle) instead of the "Pause" button (two parallel bars) even though the audio is already playing. Anyone know how to fix this?
EDIT 1:
I'd also be interested in any other solutions for playing a remote .mp3. The only requirements I have are that the user can pause/play the audio and also see what the name of the audio file (title) is.
Thank you!
Try This : It solved the Issue For Me.
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
mMediaController.show();
}
});
Simply:
#Override
public void onPrepared(MediaPlayer arg0) {
if (mediaController.isShowing==false) {mediaController.show();}
}
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
i am using the below code to play song from server.
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(playUrl);
And i am calling start method from public void onPrepared(MediaPlayer mp) method.
But what happens is sometimes it's buffering 5 to 6% and starts playing and sometimes it buffers 40 or 60 or sometimes 80%.
And i am using prepareAsync () to prepare player. So, is there any way that I can play song after 5 or 6%?
thankx
try setting an update buffer listener and play the video after certain percentage.
Edited:
boolean mediaPrepared = false;
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnBufferingUpdateListener(){
void onPrepared(MediaPlayer mp){
mediaPrepared = true;
}
});
mp.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener(){
public void onBufferingUpdate(MediaPlayer mp, int percent){
if (!mediaPrepared){
mp.prepareAsync();
}
if (percent > 5){
mp.start();
}
}
});
And make sure to handle correctly the values of the mediaPrepared flag.
I'm not sure if this will work, but maybe you can use it as a hint. Good luck!