In my project i was implemented the videoview for streaming videos. It is taking lot of time for loading and buffering the videos where as other players or browser taking far lesser time then videoview.. I was searching in internet from a couple of days couldn't able to find the proper solution for my case. I am loading the videos from Amazon S3 bucket i don't think it is because of server
private void playVideo() {
vidUri = Uri.parse(movieUrl);
vidControl = new CustomMediaControl(this, new CustomMediaControl.MediaFullScreen() {
#Override
public void fullScreenButtonClicked() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
#Override
public void fullScreenButtonExited() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
});
videoPlayer.setMediaController(vidControl);
videoPlayer.setVideoURI(vidUri);
videoPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.start();
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
progressBar.setVisibility(View.GONE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
progressBar.setVisibility(View.VISIBLE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
progressBar.setVisibility(View.GONE);
return true;
}
}
return false;
}
});
}
});
videoPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("Media Details", "hello");
return true;
}
});
videoPlayer.start();
videoPlayer.seekTo(stopPosition);
}
I was also looked into the below links Link1 and Link2.
Let me know if you need more clarity
Related
I'm trying to return the current state of the media player because I want to check that the media player has not loaded a song yet so I can provide a popup to choose an audio file.
Code in other class
public Sound(int buttonID, Activity _activity) {
super();
this.activity = _activity;
button = (Button) activity.findViewById(buttonID);
mp = new MediaPlayer();
}
Code to check if an audio file is loaded
sound.button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(//no audio file loaded){
Intent intent = new Intent(MainActivity.this, Pop.class);
startActivityForResult(intent, PICK_AUDIO_REQUEST);
}
else if(sound.mp.isPlaying()) {
sound.mp.pause();
}
else{
sound.mp.seekTo(0);
sound.mp.start();
}
}
});
Using the answer, this is the code I came up with:
sound.button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
sound.mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
isPrepared = true;
}
});
if(!isPrepared){
Intent intent = new Intent(MainActivity.this, Pop.class);
startActivityForResult(intent, PICK_AUDIO_REQUEST);
}
else if(sound.mp.isPlaying()) {
sound.mp.pause();
}
else{
sound.mp.seekTo(0);
sound.mp.start();
}
}
});
Perhaps the following could help...
MediaPlayer.setOnBufferingUpdateListener(...);
public void onBufferingUpdate(MediaPlayer mp, int percent)
{
//while MediaPlayer's buffer been update
}
MediaPlayer.setOnPreparedListener(...);
public void onPrepared(MediaPlayer mp)
{
//while MediaPlayer is ready to play
}
MediaPlayer.setOnCompletionListener(...);
public void onCompletion(MediaPlayer mp)
{
//while MediaPlayer played to the end
}
MediaPlayer.setOnErrorListener(...);
public boolean onError(MediaPlayer mp, int what, int extra)
{
//while MediaPlayer has error ocurred
}
Also, your class must implement OnAudioFocusChangeListener, and create the following method
public boolean requestAudioFocus()
{}
public boolean abandonAudioFocus()
{}
public void onAudioFocusChange(int focusChange)
{}
You may considered to put your MediaPlayer into a Service class.
I'm afraid that there is no such method. You have to check it yourself. It's not too hard to follow MeidaManager state with the MediaPlayer's StateDiagram. The easiest way is to declare a boolean flag isPrepared / isReadyToPlay and set it to true in onPrepared() callback of the OnPreparedListener.
i am displaying images and video in imageview and videoview but the issue is when video is
playing onpreparedlistener called but when video finish oncompletion listener not called
when videoview complete i increment the i for next video or images
also it gives me error in logcat like this but video is playing
10-29 20:12:47.770: E/MediaPlayer(3975): error (1, -2147483648)
private void nextVideo(String path){
mImageview.setVisibility(View.GONE);
if(mVideoview.getVisibility()==View.GONE){
mVideoview.setVisibility(View.VISIBLE);
}
controller = new MediaController(HomeActivityNewViewPager.this);
mVideoview.setVideoURI(Uri.parse(path));
mVideoview.setMediaController(null);
controller.setMediaPlayer(mVideoview);
mVideoview.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
mVideoview.start();
long duration = mVideoview.getDuration();
second=duration;
//handler.removeCallbacks(runnable);
//handler.postDelayed(runnable,second);
}
});
mVideoview.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
Log.v("video view completed","---"+i);
mp.reset();
if(automode){
if(i==myplaylistlocal.size() || i>myplaylistlocal.size())
{
String checkcount=spreferences.getString("roundcount", "");
Log.v("roundcount==Before Integer.parseInt","---->"+roundcount);
if(roundcount>=Integer.parseInt(checkcount))
{
roundcount=0;
Log.v("roundcount==After Integer.parseInt","---->"+roundcount);
updateplaylist();
}
i=0;
indexplus();
imagesautomode();
i++;
}
else if(i==myplaylistlocal.size()-1)
{
imagesautomode();
i++;
}
else{
imagesautomode();
}
}
else{
i++;
images();
}
}
});
mVideoview.setOnErrorListener(new OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.v("Error in video playing","----->"+i);
return true;
}
});
}
Either way, the error referenced above is MEDIA_ERROR_UNKNOWN. If this video was made for this app, I would make sure that it is properly encoded for Android. Also make sure that is clearly defines its endpoint.
http://developer.android.com/reference/android/media/MediaPlayer.html#MEDIA_ERROR_UNKNOWN
this is a work around but could possbly work in your situation:
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
if(what == MediaPlayer.MEDIA_ERROR_UNKNOWN)
//ERROR UNKNOWN - COULD BE IMPROPERLY FORMATTED VIDEO {
//MOVE ON TO NEXT VIDEO
//DO LOGGING
}
}
I've developed an app which takes an advantage of the native Android's MediaPlayer. The source code of my class making use of Media Player is below.
The problem is that only on some devices after some miliseconds of playback (I hear only voice, the screen remains black) I keep getting error(100,0) which according to the documentation says
public static final int MEDIA_ERROR_SERVER_DIED
Media server died. In this case, the application must release the MediaPlayer object and instantiate a new one.
On forums I've found out that I need to reset the player every time I get it... but I get it after just a short moment and then it dies forever. I cannot reset the player every second since playback is useless. I cannot get why some devices have this problem and others not. The one that I know has Android OS > 4.0.
Of course, first init() and then showVideo() are getting called. The last onError with code 100 is then called. What's a potential solution to make the streams run continuously and not break?
public class NativePlayer extends Player implements OnBufferingUpdateListener,
OnCompletionListener, OnErrorListener, OnInfoListener {
private VideoView videoview;
private PlayerListener listener;
private MainActivity context;
private final Logger logger = LoggerFactory.getLogger(NativePlayer.class);
#Override
public void init(MainActivity activity) {
this.videoview = (VideoView) activity.findViewById(R.id.video);
context = activity;
}
#Override
public void showVideo(final String url, final PlayerListener _listener) {
listener = _listener;
videoview.setVisibility(View.VISIBLE);
try {
Uri video = Uri.parse(url);
videoview.setVideoURI(video);
} catch (Exception e) {
logger.error("Error playing video", e);
listener.onVideoError();
return;
}
videoview.setOnCompletionListener(this);
videoview.setOnErrorListener(this);
videoview.requestFocus();
videoview.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
videoview.start();
if (listener != null) {
listener.onVideoStarted();
}
}
});
}
#Override
public void onStop() {
stop();
}
private void stop() {
if (videoview == null) {
return;
}
if (videoview.isPlaying()) {
videoview.stopPlayback();
}
}
#Override
public void onDestroy() {
}
#Override
public void onCompletion(MediaPlayer mp) {
stop();
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
if (listener != null) {
listener.onVideoError();
}
return false;
}
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (listener != null) {
listener.onInfo(what, extra);
}
return false;
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
if (listener != null) {
listener.onBufferingUpdate(percent);
}
}
}
I had same problem (error 100, mediaplayer died, etc.).
I resolve it by using .stopPlayback(), and starting stream again.
Below is my part of code:
private void startWatchVideo(final string video_link) {
videoViewVA.setMediaController(new MediaController(this));
videoViewVA.setVideoURI(Uri.parse(video_link));
videoViewVA.requestFocus();
videoViewVA.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer media) {
media.start();
}
});
videoViewVA.setOnErrorListener(new OnErrorListener() {
#Override
public boolean onError(MediaPlayer media, int what, int extra) {
if (what == 100)
{
videoViewVA.stopPlayback();
startWatchVideo(video_link);
}
return true;
}
});
}
On practice it looks like video is just slows down
My ProgressDialog will not show up. In my program the user selects bitrate from a pop up menu, the content is fetched online and displayed in VideoView.
However, all I get is a black screen while the video loads and the progressDialog is display for a split second (or less) at end before the video finally loads.
private void showPopupMenu(View v){
popupMenu = new PopupMenu(VideoPlayer.this, v);
if(bitRates != null){
int menuItem = 0;
int index = bitRates.size()-1;
popupMenu.getMenu().add(0,menuItem, 0,"Hide menu");
for(int i=1;i<bitRates.size();i++){
menuItem = i;
popupMenu.getMenu().add(0,menuItem, 0,"Quality"+" : "+bitrateCheck(bitRates.get(index))).setCheckable(true);
Log.i("ITEM",qualityList.get(i)+" : "+bitRates.get(i));
index--;
}
popupMenu.getMenu().add(0,menuItem++, 0,"Catalog");
}
popupMenu.show();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(final MenuItem item) {
p_dialog = ProgressDialog.show(VideoPlayer.this, "", "Loading...");
//get current position of video to seek to
final int position = mVideoView.getCurrentPosition();
new Thread() {
public void run() {
try{
runOnUiThread(new Runnable() {
public void run() {
if(item.getTitle().equals("Catalog")){
backButtonVideo(new View(VideoPlayer.this));
}
else if(item.getTitle().equals("Hide menu")){
popupMenu.dismiss();
mVideoView.start();
}
else{
play(streamUrls.get(item.getItemId()),position);
}
}
});
}
catch (Exception e) {
Log.e("tag", e.getMessage());
}
p_dialog.dismiss();
}
}.start();
return true;
}
});
}
public void play(String _videoUri, int position){
Log.i(TAG,"URI is : "+Uri.parse(_videoUri).toString());
//View view = new View()
MediaController mc = new MediaController(VideoPlayer.this);
mVideoView.setMediaController(mc);
mVideoView.setVideoURI(Uri.parse(_videoUri));
mVideoView.requestFocus();
mVideoView.seekTo(position);
mVideoView.start();
}
////////////////////////Edit with new Code: as per suggestions/////////////////////
Now the dialog does not show at all.
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mVideoView.start();
}
});
///////////////////////////////////////////////////////////////////////////////////
popupMenu.show();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(final MenuItem item) {
//get current position of video to seek to
final int position = mVideoView.getCurrentPosition();
p_dialog = ProgressDialog.show(VideoPlayer.this, "", "Loading...");
try{
if(item.getTitle().equals("Catalog")){
backButtonVideo(new View(VideoPlayer.this));
}
else if(item.getTitle().equals("Hide menu")){
popupMenu.dismiss();
mVideoView.start();
}
else{
play(streamUrls.get(item.getItemId()),position);
}
}
catch (Exception e) {Log.e("tag", e.getMessage());}
return true;
}
});
}
public void play(String _videoUri, int position){
Log.i(TAG,"URI is : "+Uri.parse(_videoUri).toString());
MediaController mc = new MediaController(VideoPlayer.this);
mVideoView.setMediaController(mc);
mVideoView.setVideoURI(Uri.parse(_videoUri));
mVideoView.requestFocus();
mVideoView.seekTo(position);
p_dialog.dismiss();
}
Firstly, it makes no sense to create a separate thread only to run something back on the UI thread (why do you create the thread in the first place then?).
onMenuItemClick should already be called by the UI thread (callbacks for UI elements generally do this).
What you should look at is using a MediaPlayer.OnPreparedListener with VideoView.setOnPreparedListener. This will give you an indication of when the video is ready to be played.
I did some rearrangement as per Che Jami and got it to work. Thanks
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
p_dialog.dismiss();
mVideoView.start();
}
});
////////////////////////////////////////////////////////////////////////////////
popupMenu.show();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(final MenuItem item) {
//get current position of video to seek to
final int position = mVideoView.getCurrentPosition();
try{
if(item.getTitle().equals("Catalog")){
backButtonVideo(new View(VideoPlayer.this));
}
else if(item.getTitle().equals("Hide menu")){
popupMenu.dismiss();
mVideoView.start();
}
else{
p_dialog = ProgressDialog.show(VideoPlayer.this, "", "Loading new stream");
play(streamUrls.get(item.getItemId()),position);
}
}
catch (Exception e) {Log.e("tag", e.getMessage());}
return true;
}
});
}
public void play(String _videoUri, int position){
Log.i(TAG,"URI is : "+Uri.parse(_videoUri).toString());
MediaController mc = new MediaController(VideoPlayer.this);
mVideoView.setMediaController(mc);
mVideoView.setVideoURI(Uri.parse(_videoUri));
mVideoView.requestFocus();
mVideoView.seekTo(position);
}
I have the same problem...i've tried you solution but my progress gets blocked...everything stops...and video doesn't show up...it seems that onPrepareListener is never called up...any ideas? Also it seems that setVideoURI has never passed in code...:/
I have different versions of code...with threads, with runOnUI, with AsyncTask, without everything...nothing seems to be working fully. something is always missing.
EDIT:
I have function that I'm calling in onClickListener
Here is a code like yours without any threads:
Version 1: Video starts after few seconds, progress dialog just show for a moment when video starts. Progress isn't showed from the beginning.
public void loadService(final int mode) {
//Version 1
// Show dialog
loadService = new ProgressDialog(activity);
loadService.setTitle("Loading service");
loadService.setMessage("Please wait...");
loadService.setCancelable(false);
loadService.show();
// Hide progress dialog after 15 seconds if nothing happens
DuoTVGuiHandler.progressBarProttection(loadService, 15);
// Setup video view for playback
if (mode == STAND_ALONE) {
setupVideoView(((DuoTVGuiActivity) activity).getVideoPlayback());
}
if (mode == WIDGET_MODE) {
setupVideoView(((MainActivity) activity).getVideoViewWidgetMode());
}
}
/** Setup video view for playback */
public void setupVideoView(final VideoView videoView) {
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
loadService.dismiss();
videoView.start();
}
});
videoView.setVideoURI(Uri.parse(channels.get(index).getFilePath()));
}
Version 2 with thread and handler...progress dialog is showed...its spinning...video shows for a second...and the app crashes...WrongThread for UI exception...but when i move setVideoURI in runOnUiThread...progress just stays forever...and setOnVideoURI is never finished.
public void loadService(final int mode) {
// //////////////////////////////
// Version 2
// //////////////////////////////
// Show dialog
loadService = new ProgressDialog(activity);
loadService.setTitle("Loading service");
loadService.setMessage("Please wait...");
loadService.setCancelable(false);
loadService.show();
final Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
loadService.dismiss();
super.handleMessage(msg);
}
};
Thread loadVideoPath = new Thread(new Runnable() {
public void run() {
if (mode == STAND_ALONE) {
((DuoTVGuiActivity) activity)
.getVideoPlayback()
.setVideoURI(
Uri.parse(channels.get(index).getFilePath()));
}
if (mode == WIDGET_MODE) {
((MainActivity) activity)
.getVideoViewWidgetMode()
.setVideoURI(
Uri.parse(channels.get(index).getFilePath()));
}
handler.sendEmptyMessage(0);
}
});
loadVideoPath.start();
}
Hope you have some idea...I've lost few days on this...and cant see solution...for this pretty basic thing...it drives me crazy :)
Does anyone know if it's possible to detect when a VideoView is buffering?
I want to show a ProgressDialog when the video is buffering.
So far I tried using a OnPreparedListener, but that only works when the video is first loaded. If a video is playing and the user moves the scrub bar to a different point the video is still "prepared" even though it is buffering.
I also tried (I know this is awful) an AsyncThread that just busy waits on isPlaying():
private class BufferTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void...voids) {
final VideoView videoView = (VideoView)findViewById(R.id.video);
while (!videoView.isPlaying()) { }
return null;
}
protected void onPostExecute(Void v) {
// Hide the dialog here...
}
}
This doesn't work because as soon as you call start() a VideoView seems to be considered playing even though it is buffering.
The only solution I can think of is building a custom VideoView type class so I can access its MediaPlayer instance.
Any ideas? Thanks for reading.
Since API level 17, you can now access the InfoListener from the MediaPlayer:
final MediaPlayer.OnInfoListener onInfoToPlayStateListener = new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
mProgressBar.setVisibility(View.GONE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
mProgressBar.setVisibility(View.VISIBLE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
mProgressBar.setVisibility(View.GONE);
return true;
}
}
return false;
}
});
mVideoView.setOnInfoListener(onInfoToPlayStateListener);
I came with the following hack in order to not implement a custom VideoView. The idea is to check every 1 second if the current position is the same as 1 second before. If it is, the video is buffering. If not, the video is really playing.
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
int duration = videoView.getCurrentPosition();
if (old_duration == duration && videoView.isPlaying()) {
videoMessage.setVisibility(View.VISIBLE);
} else {
videoMessage.setVisibility(View.GONE);
}
old_duration = duration;
handler.postDelayed(runnable, 1000);
}
};
handler.postDelayed(runnable, 0);
videoMessage is just a TextView with the text "Buffering..." placed in the center of my VideoView.
Following code will show a buffering dialog every time the VideoView is buffering.
final ProgressDialog bufferingDialog;
bufferingDialog = ProgressDialog.show(context,
"Buffering", "Please wait", true, true);
VideoView videoView;
videoView = (VideoView) findViewById(R.id.video_view);
videoView.setVideoPath(path);
videoView.setMediaController(new MediaController(context));
videoView.requestFocus();
videoView.start();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START)
bufferingDialog.show();
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END)
bufferingDialog.dismiss();
return false;
}
});
}
});
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
bufferingDialog.dismiss();
return false;
}
});
VideoView showing Progress while Buffering.
Below code worked for me:
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mp) {
mp.start();
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
progressBar.setVisibility(View.GONE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
progressBar.setVisibility(View.VISIBLE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
progressBar.setVisibility(View.GONE);
return true;
}
}
return false;
}
});
}
});
I'm working on something similar, and couldn't come up with a great solution. Some interesting solutions were posted here that you should check out if you haven't seen them.
Anyway, I came up with the following hack that was hinted at in the above thread and works ok for now.
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
float temp = ((float)mp.getCurrentPosition() / (float)mp.getDuration())*100;
if(Math.abs(percent - temp) < 1) {
buffer_fail++;
if(buffer_fail == 15) {
//buffer failed
}
}
}
This worked for me
boolean b_start = true;
boolean b_end = true;
final MediaPlayer.OnInfoListener onInfoToPlayStateListener = new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
dialog1.setVisibility(View.GONE);
b_end = false;
b_start = false;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
if (b_start){
dialog1.setVisibility(View.VISIBLE);
}
b_start = true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
if(b_end){
dialog1.setVisibility(View.VISIBLE);
}
b_end = true;
}
}
return false;
}
};
videoView.setOnInfoListener(onInfoToPlayStateListener);