I'm trying to play a video with VideoView in WindowManager. I'm using the StandOutLibrary for this. I've been pretty successful so far except a couple of things.
MediaController obviously does not work in this case since it needs an activity. So I wrote my custom view to control the videoview. Here is the result-
Everything works except the seekbar after pausing. After I pause the video and start it again, the seekbar refuses to update. Here's my code to play/pause and update seekbar-
play.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
if (playing) {
vv.pause();
play.setImageResource(R.drawable.ic_media_play);
playing = !playing;
} else {
vv.start();
play.setImageResource(R.drawable.ic_media_pause);
playing = !playing;
}
}
});
vv = (VideoView) mView.findViewById(R.id.videoView);
vv.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
sb.setMax(vv.getDuration());
sb.postDelayed(onEverySecond, 60);
}
});
vv.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
close(id);
}
});
sb = (SeekBar) mView.findViewById(R.id.sbar);
sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
vv.seekTo(sb.getProgress());
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
vv.seekTo(sb.getProgress());
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (fromUser) {
vv.seekTo(progress);
// vv.start();
}
}
});
Where is my mistake?
Also the second problem comes after resizing the window. Normally, all the views take the new layout size after resizing the window. I've tried this with a SurfaceView too and it works. But the VideoView does not take the new size. Here is the result after changing the window size-
Can anyone help me out regarding these two? Thanks in advance!
You should use RelativeLayout as wrapper of your VideoView.
Reference: click here
Related
I have the following code to add a SeekBar to a video:
final VideoView videoView = (VideoView) findViewById(R.id.videoView);
final MediaController mediaController = new MediaController(this) {
...
// Commented out irrelevant code.
}
mediaController.show();
mediaController.setAnchorView(videoView);
videoView.setMediaController(mediaController);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
final int topContainerId1 = getResources().getIdentifier("mediacontroller_progress",
"id", "android");
final SeekBar seekbar = (SeekBar) mediaController.findViewById(topContainerId1);
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
int overall_progress = 0;
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
...
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
videoView.seekTo((int) (videoView.getDuration() * (seekBar.getProgress() / 1000.0)));
}
});
}
});
Everything works fine, and the seeker indicator is aligned with the video while it is playing. When I move the seek button manually, the video goes to the right place.
My Problem: If I pause the video and then start playing again, the seekbar progress indicator no longer moves even though the video plays again. I checked to see if onProgressChanges() was called in this situation, but it is never even called! Does anyone know a fix for this? It appears that this person also had the problem, but nobody answered their post: Seekbar OnProgressChanged doesn't get fired when moving manually
I am actually creating an app with a button, a seekbar and an an image. The button is used to Play/Pause the music. the music played smooth before adding the seekbar. But, after writing the code for seekbar to progress with the position of music, the music seems to be a bit choppy.
Also, i want to reset the position of seekbar to start and change the text on button to "Play" after the music is finished playing.
Can any one tell me why the music is choppy after implementing seekbar?
Also, suggest me how to deal after the music is finished playing.
The coded i used is below:
public class MainActivity extends ActionBarActivity {
private MediaPlayer song;
private SeekBar seekbar;
private final Handler handler = new Handler();
private final Runnable updatePositionRunnable = new Runnable() {
public void run() {
updatePosition();
}
};
//private boolean isPlaying = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
seekbar = (SeekBar)findViewById(R.id.musicSeekBar);
song = MediaPlayer.create( MainActivity.this, R.raw.xyz);
seekbar.setMax(song.getDuration());
final Button playButton = (Button)findViewById(R.id.playButton);
playButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(song.isPlaying()){
playButton.setText("Play");
song.pause();
//isPlaying = false;
handler.removeCallbacks(updatePositionRunnable);
}
else{
playButton.setText("Pause");
song.start();
//isPlaying = true;
updatePosition();
}
}
});
song.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
playButton.setText("Play");
//seekbar.setProgress(0);
//mp.stop();
}
});
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
song.seekTo(progress);
}
});
private void updatePosition(){
handler.removeCallbacks(updatePositionRunnable);
seekbar.setProgress(song.getCurrentPosition());
handler.postDelayed(updatePositionRunnable, 2000);
}
#Override
public void onBackPressed() {
super.onBackPressed();
song.stop();
song.release();
}
When you update the progress on the seekbar from your updatePosition method every 2 seconds, the onProgressChanged method in your listener will be called, which will set the position of the playback and cause a slight blip. You might expect onProgressChanged to be called only when the user interacts with the SeekBar but unfortunately that isn't the case.
I'm not aware of a clean solution to this. What you can do is set a boolean flag in your code immediately before calling seekbar.setProgress that indicates the next onProgressChanged callback was not caused by the user, so you can ignore it. You should use an AtomicBoolean for this purpose because the events may come from different threads.
this worked for me:
sBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
boolean userTouch;
#Override
public void onStopTrackingTouch(SeekBar arg0) {
userTouch = false;
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
userTouch = true;
}
#Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
if(mPlayer.isPlaying() && arg2)
mPlayer.seekTo(arg1);
}
});
i have the following code:
final SeekBar videoBar = (SeekBar) findViewById(R.id.videoBar);
final VideoView videoView = (VideoView) findViewById(R.id.videoViewPaint);
videoView.setVideoPath(videoPath);
videoView.start();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
long duration = videoView.getDuration();
videoBar.setMax((int) duration);
LogService.log("in runnable", "videoView duration= " + videoView.getDuration());
}
});
videoBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (isVideo) {
videoView.seekTo(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
playBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
if (isPlaying) {
// Button is ON
videoView.pause();
playBtn.setImageResource(R.drawable.play);// Do Something
isPlaying = false;
} else if (!isPlaying) {
// Button is OFF
videoView.start(); // Do Something
playBtn.setImageResource(R.drawable.pause);
isPlaying = true;
}
}
});
Now if i move the progressBar (videoBar), it takes the the video to that part of the video, but if the video plays, it does not move to progress bar, alongside. How can I make it, move the progress bar while the video is playing?
This helped me get it right, now it works. The first answer
How to use a Seekbar in android as a seekBar as well as a progressBar simultaneously?
After searching for many hours , i am asking this, any related answers are welcomed . .
I'm having a video in my R.raw folder and i am playing it in two videoview of same duration simultaneously , here is my code ,
sb = (SeekBar)findViewById(R.id.control_seekbar);
mVideoView1 = (VideoView) findViewById(R.id.surface_view1);
mVideoView1.setVideoPath("android.resource://" + getPackageName() +"/"+R.raw.play1);
mVideoView1.start();
mVideoView2 = (VideoView) findViewById(R.id.surface_view2);
mVideoView2.setVideoPath("android.resource://" + getPackageName() +"/"+R.raw.play2);
mVideoView2.start();
v1 = mVideoView1.getDuration();
v2 = mVideoView2.getDuration();
mVideoView1.setOnPreparedListener(new OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer arg0)
{
sb.setMax(mVideoView1.getDuration()+3);
sb.postDelayed(onEverySecond, 60);
}
});
sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
{
#Override
public void onStopTrackingTouch(SeekBar seekBar)
{
mVideoView1.seekTo(sb.getProgress());
mVideoView2.seekTo(sb.getProgress());
}
#Override
public void onStartTrackingTouch(SeekBar seekBar)
{
mVideoView1.seekTo(sb.getProgress());
mVideoView2.seekTo(sb.getProgress());
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser)
{
mVideoView1.seekTo(progress);
mVideoView2.seekTo(progress);
}
});
}
private Runnable onEverySecond=new Runnable()
{
#Override
public void run()
{
if(sb != null)
{
sb.setProgress(mVideoView1.getCurrentPosition());
}
if(mVideoView1.isPlaying())
{
sb.postDelayed(onEverySecond, 1000);
if(mVideoView1.getDuration() <= sb.getProgress())
{
mVideoView1.seekTo(0);
mVideoView2.seekTo(0);
}
}
}
};
and i could drag the seekbar to the new position and it is playing from the new position correctly .
But i dont want to play the video initially . It should be in pause() and as i drag the seekbar, the videoview should update to the respective position .
When i change the mVideoView.start() to pause() , i could see only a blank black screen and no update for the seekbar position change in the videoview .
in what way i could achieve it .
You have to put a media controller in your videoview.
MediaController mediaController = new MediaController(context);
myVideoView.setMediaController(mediaController).
Now when you click on your video the play, pause buttons will show.
If you dont want to play the video initially then you need not call start in onCreate()
Call it when play button is clicked.
Hope this helps you.
I intend to write a custom media controller for my app. I was planning to use seekbar to do both seeking and showing progress. Trying to implement this.
Does anyone have such implementation or am I on the wrong path ?
Finally I figured it out!!
The solution that I came up with was something like this :
First of all set the max progress for seekbar as the duration of the video
videoView.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
seekBar.setMax(videoView.getDuration());
seekBar.postDelayed(onEverySecond, 1000);
}
});
This runnable will keep on updating the progressbar :
private Runnable onEverySecond=new Runnable() {
#Override
public void run() {
if(seekBar != null) {
seekBar.setProgress(videoView.getCurrentPosition());
}
if(videoView.isPlaying()) {
seekBar.postDelayed(onEverySecond, 1000);
}
}
};
And then the setOnSeekBarChangeListener for the seekbar can be used to take the user seeks on the media. By using the fromUser boolean we can make out whether it was a call back due to user's interaction or the
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(fromUser) {
// this is when actually seekbar has been seeked to a new position
videoView.seekTo(progress);
}
}
});
You set the seconday progress.
No, you're on the right track. It is very good for displaying stuff like download progress and current location for streams (media).