I am hiding the VideoView initially and when the video is loaded I am showing the VideoView. But onPrepared is never called if the VideoView is invisible initially. However onPrepared is called properly if VideoView is visible. Is there any way to hide the videoView until video is loaded. Any help would be appreciated. Thanks!
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<VideoView
android:id="#+id/video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:visibility="invisible" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
VideoView videoView = (VideoView) findViewById(R.id.video);
Uri videoUri = Uri.parse(url);
videoView.setVideoURI(videoUri);
videoView.requestFocus();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
Toast.makeText(mActivity, "on prepared", Toast.LENGTH_SHORT).show();
videoView.setVisibility(View.VISIBLE);
}
});
}
You could try setting alpha channel of video view to 0 or close to 0.
Solved it making its layout invisible instead of videoView itself.
Thanks to #J.Kowalski .
Layout:
<FrameLayout
android:id="#+id/layout_video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<VideoView
android:id="#+id/video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:scrollbars="none"/>
</FrameLayout>
<ProgressBar
android:id="#+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
/>
Set OnPreparedListener:
videoView.setOnPreparedListener(this);
Show progress bar before ready:
#Override
public void showProgress() {
progress.setVisibility(View.VISIBLE);
layoutVideoView.setVisibility(View.INVISIBLE);
}
Load video URI:
#Override
public void loadVideo(Uri uri) {
videoView.setVideoURI(uri);
}
When its ready, onPrepared is called:
#Override
public void onPrepared(MediaPlayer mp) {
Log.d("debug", "onPrepared");
iStepPreviewPresenter.onVideoViewReady();
}
Finally show layout and start video:
#Override
public void hideProgress() {
progress.setVisibility(View.INVISIBLE);
layoutVideoView.setVisibility(View.VISIBLE);
}
#Override
public void startVideo() {
videoView.start();
}
Nailed it!
It can be achieved by one of these tricks
You can set the height and width of the VideoView to 1px until the video is prepared and then switch to full screen by changing the properties to match parent
As #FDIM said in his answer, we can set the alpha value of the view to 0 until video is prepared. But it works only if we use TextureView to load the video. It doesn't work with normal VideoView. Here is a custom VideoView extending TextureView which mimics the default VideoVideo implementation. This class can be directly used in xml file and can set the alpha to 0 to hide the video.
public class TextureVideoView extends TextureView implements SurfaceTextureListener {
private MediaPlayer mMediaPlayer;
public TextureVideoView(Context context) {
super(context);
init();
}
public TextureVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mMediaPlayer = new MediaPlayer();
this.setSurfaceTextureListener(this);
}
public void seekTo(int msec) {
mMediaPlayer.seekTo(msec);
}
public void setVideoPath(final String path) throws IOException {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(path);
mMediaPlayer.prepare();
}
public void setVideoPath(FileDescriptor fd, long offset, long length) throws IOException {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(fd, offset, length);
mMediaPlayer.prepare();
}
public void setVideoURI(Context context, Uri uri) throws IOException {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(context, uri);
}
public void setOnPreparedListener(OnPreparedListener onPreparedListener) {
mMediaPlayer.setOnPreparedListener(onPreparedListener);
}
public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
mMediaPlayer.setOnCompletionListener(onCompletionListener);
}
public void setOnErrorListener(OnErrorListener onErrorListener) {
mMediaPlayer.setOnErrorListener(onErrorListener);
}
public void start() {
mMediaPlayer.start();
}
public void pause() {
mMediaPlayer.pause();
}
public void setVolume(float leftVolume, float rightVolume ) {
mMediaPlayer.setVolume(leftVolume, rightVolume);
}
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
public void stopPlayback() {
mMediaPlayer.stop();
}
public void reset() {
mMediaPlayer.reset();
}
public void release() {
mMediaPlayer.release();
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height) {
mMediaPlayer.setSurface(new Surface(surface));
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height) {
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
An easier workaround:
Just add a dummy parentview for the videoview and set the visiblity for that parentview instead of changing the visibility of the videoview itself.
Related
I have bit of trouble playing back video in my app. I have the very similar code as below playing back my audio files, however, when I try to play video I'm not seeing a picture, I can still hear the narration but no video. Just to exclude encoding, I dropped in my assets a file from my cell that was created on my cell and I was trying to play it back using the above method without luck. Any thoughts would be appreciated, Thank you.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_audio_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<VideoView
android:layout_weight="0.3"
android:id="#+id/videoView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ListView
android:id="#+id/fragmentVidListView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
public class MediaPlayer extends AppCompatActivity implements OnPreparedListener, MediaController.MediaPlayerControl {
private static final String TAG = "VideoPlayer";
private android.media.MediaPlayer mediaPlayer;
private MediaController mediaController;
private String videoFileName= "test2.mp4";
private Handler handler = new Handler();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_video_view);
mediaPlayer = new android.media.MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaController = new MediaController(this);
try {
AssetFileDescriptor descriptor = MediaPlayer.this.getAssets().openFd(videoFileName);
long start = descriptor.getStartOffset();
long end = descriptor.getLength();
mediaPlayer.setDataSource(descriptor.getFileDescriptor(), start, end);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
Log.e(TAG, "Could not open file " + videoFileName + " for playback.", e);
}
}
#Override
public void onPrepared(android.media.MediaPlayer mp) {
Log.d(TAG, "onPrepared");
mediaController.setMediaPlayer(this);
mediaController.setAnchorView(findViewById(R.id.videoView1));
handler.post(new Runnable() {
public void run() {
mediaController.setEnabled(true);
mediaController.show();
}
});
}
#Override
protected void onStop() {
super.onStop();
mediaController.hide();
}
#Override
public boolean onTouchEvent(MotionEvent event) { //the MediaController will hide after 3 seconds - tap the screen to make it appear again
mediaController.show();
return false;
}
public void start() {
mediaPlayer.start();
}
public void pause() {
mediaPlayer.pause();
}
public int getDuration() {
return mediaPlayer.getDuration();
}
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
public void seekTo(int i) {
mediaPlayer.seekTo(i);
}
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
public int getBufferPercentage() {
return 0;
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
#Override
public void onStart() {
super.onStart();
}
}
I am doing an Android project based on Video view. I want to show play button before the user clicks play, when user decides to pause video - pause button shows up. Clicking on pause button should trigger playing the video again from the same place where it was paused (like YouTube video).
im1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vv1.setVideoURI(Uri.parse("android.resource://com.example.cm.filmfestival/" + R.raw.mission));
im1.setVisibility(View.INVISIBLE);
im2.setVisibility(View.INVISIBLE);
vv1.start();
}
});
im2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vv1.stopPlayback();
im2.setVisibility(View.VISIBLE);
im1.setVisibility(View.INVISIBLE);
}
});
#Override
public boolean onTouch(View v, MotionEvent event) {
im1.setVisibility(View.VISIBLE);
vv1.start();
im2.setVisibility(View.VISIBLE);
vv1.stopPlayback();
return true;
}
Use the code below
<VideoView
android:id="#+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
public VideoView myVideoView;
private int position = 0;
private MediaController mediaControls;
// set the media controller buttons
if (mediaControls == null)
{
mediaControls = new MediaController(MainActivity.this);
}
// initialize the VideoView
myVideoView = (VideoView) findViewById(R.id.video_view);
try
{
// set the media controller in the VideoView
myVideoView.setMediaController(mediaControls);
// set the uri of the video to be played
myVideoView.setVideoURI(Uri.parse("your UrI"));
} catch (Exception e)
{
Log.e("Error", e.getMessage());
e.printStackTrace();
}
myVideoView.requestFocus();
// we also set an setOnPreparedListener in order to know when the video
// file is ready for playback
myVideoView.setOnPreparedListener(new OnPreparedListener()
{
public void onPrepared(MediaPlayer mediaPlayer)
{
// if we have a position on savedInstanceState, the video
// playback should start from here
myVideoView.seekTo(position);
System.out.println("vidio is ready for playing");
if (position == 0)
{
myVideoView.start();
} else
{
// if we come from a resumed activity, video playback will
// be paused
myVideoView.pause();
}
}
});
Set an OntouchListener on your VideoView and then in Ontouch callback check if the video is playing or paused before pausing or playing it.
private boolean stopped = false;
private ImageView postVideoPlaypauseIcon;
//set it to any play/pause icon
postVideoPlaypauseIcon = mView.findViewById(R.id.playpause_icon);
private int stopPosition;
Add above code.
then, add CustomVideoView class, make VideoView extend it and create an object video and use findviewbyid
public class CustomVideoView extends VideoView {
private PlayPauseListener mListener;
public CustomVideoView(Context context) {
super(context);
}
public CustomVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setPlayPauseListener(PlayPauseListener listener) {
mListener = listener;
}
#Override
public void pause() {
super.pause();
if (mListener != null) {
mListener.onPause();
}
}
#Override
public void start() {
super.start();
if (mListener != null) {
mListener.onPlay();
}
}
public static interface PlayPauseListener {
void onPlay();
void onPause();
}
}
replace xml for VideoView with below code
`<package-name.CustomVideoView
android:id="#+id/custom_videoview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>`
Finally,
add setOnTouchListener for listening to touch.
video.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(stopped == false){
stopPosition = postVideo.getCurrentPosition();
video.pause();
stopped = true;
} else if(stopped == true){
video.seekTo(stopPosition);
video.start();
stopped = false;
}
Log.e("TAP","from video ");
return false;
}
});
add setPlayPauseListener on your videoView object
video.setPlayPauseListener(new CustomVideoView.PlayPauseListener() {
#Override
public void onPlay() {
System.out.println("Play!");
videoPlaypauseIcon.setVisibility(View.VISIBLE);
}
#Override
public void onPause() {
System.out.println("Pause!");
videoPlaypauseIcon.setVisibility(View.INVISIBLE);
}
});
used this for reference
**In Android Application Please Suggest how can we setDuration of video... My video length is currently more than 2 minutes.
*1.videoview doesnot giving setDuration ...
2. how to setDuration in videoview***
public class MainActivity extends Activity {
VideoView video;
MediaPlayer mp;
Button play;
int playtime=10000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
video=(VideoView)findViewById(R.id.videoView1);
video.setLongClickable(true);
play=(Button)findViewById(R.id.btn1);
Uri uri=Uri.parse("android.resource://" + getPackageName() +"/"+R.drawable.b);
video.setVideoURI(uri);
video.setMediaController(new MediaController(this));
//video.setDuration(playtime);
MediaController mp=new MediaController(this);
play.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v)
{
if(video.getDuration()<=playtime)
{
video.setVisibility(v.VISIBLE);
video.requestFocus();
video.start();
play.setEnabled(false);
}
else
{
video.stopPlayback();
}
return true;
}
});
video.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
play.setEnabled(true);
video.setVisibility(View.GONE);
play.setFocusableInTouchMode(true);
play.requestFocus();
}
});
}
2. Xml and here is the XML Snippet which is ok..
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<VideoView
android:id="#+id/videoView1"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:visibility="gone"
android:layout_centerHorizontal="true" />
<Button
android:id="#+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="play"/>
</RelativeLayout>
You need to implement MediaPlayerControl to MediaController Like this.
mp.setMediaPlayer(new MediaPlayerControl() {
#Override
public void start() {
}
#Override
public void seekTo(int pos) {
}
#Override
public void pause() {
}
#Override
public boolean isPlaying() {
return false;
}
#Override
public int getDuration() {
return 0; // Pass your duration here
}
#Override
public int getCurrentPosition() {
return 0;
}
#Override
public int getBufferPercentage() {
return 0;
}
#Override
public boolean canSeekForward() {
return false;
}
#Override
public boolean canSeekBackward() {
return false;
}
#Override
public boolean canPause() {
return false;
}
});
Replace this lines
video.setMediaController(new MediaController(this));
//video.setDuration(playtime);
MediaController mp=new MediaController(this);
With
MediaController mp=new MediaController(this);
video.setMediaController(mp);
I implemented a simple MediaController using this code (which I found here on stackoverflow). My first problem is that I want the MediaController to be visible always. I can override the hide() method, but at this point I cannot exit from my app with the BACK button. I read that overriding dispatchKeyEvent() might solve the problem, but it has no effect for me.
Actually my second question is how to make active buttons when using this? Not new buttons in the media player, but I want them in another layout (I will have about 15 different buttons). If I make a new LinearLayout in my xml, that layout with the buttons is NOT active until the mediacontroller is on the screen. The touchEvent makes the MediaController disappear and THEN I can press the buttons. Is it possible to have active buttons and a never-disappearing MedaiController on the screen at the same time?
public class PlayAudioActivity extends Activity implements MediaPlayerControl {
private static final String PLAY_AUDIO = "PLAY_AUDIO";
private MediaController mMediaController;
private MediaPlayer mMediaPlayer;
private Handler mHandler = new Handler();
static Context context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context=this;
mMediaPlayer = new MediaPlayer();
mMediaController = new MediaController(this)
/* {
#Override
public void hide()
{
mMediaController.show(0);
}
}*/;
mMediaController.setMediaPlayer(PlayAudioActivity.this);
mMediaController.setAnchorView(findViewById(R.id.audioView));
// String audioFile = "" ;
try {
mMediaPlayer.setDataSource(this,Uri.parse("android.resource://com.example.audioplayer/raw/song"));
mMediaPlayer.prepare();
} catch (IOException e) {
Log.e(PLAY_AUDIO, "Could not open file " + " " + " for playback.", e);
}
mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mHandler.post(new Runnable() {
public void run() {
mMediaController.show(0);
mMediaPlayer.start();
}
});
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
mMediaPlayer.stop();
mMediaPlayer.release();
}
#Override
public boolean canPause() {
return true;
}
#Override
public boolean canSeekBackward() {
return false;
}
#Override
public boolean canSeekForward() {
return false;
}
#Override
public int getBufferPercentage() {
int percentage = (mMediaPlayer.getCurrentPosition() * 100) / mMediaPlayer.getDuration();
return percentage;
}
#Override
public int getCurrentPosition() {
return mMediaPlayer.getCurrentPosition();
}
#Override
public int getDuration() {
return mMediaPlayer.getDuration();
}
#Override
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
#Override
public void pause() {
if(mMediaPlayer.isPlaying())
mMediaPlayer.pause();
}
#Override
public void seekTo(int pos) {
mMediaPlayer.seekTo(pos);
}
#Override
public void start() {
mMediaPlayer.start();
}
/*public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
finish();
return super.dispatchKeyEvent(event);
}*/
#Override
public boolean onTouchEvent(MotionEvent event) {
mMediaController.show(0);
return false;
}
}
My xml layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/audioView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
<LinearLayout
android:id="#+id/audioView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</LinearLayout>
</LinearLayout>
I am using VideoView to play video files. I am using seekTo function in order to play the video from where it has been left off. However, I wanted to do some operations when the seek operation is finished. For that I need to use onSeekCompleteListener; however, onSeekCompleteListener is not supported with VideoView; it can be used with MediaPlayer. My Question is that "is there any way by which I can use onSeekCompleteListener" with VideoView?
Thanks alot
There is no need to create a custom VideoView.
You can access the MediaPlayer from the onPrepared method of the VideoView and then set the OnSeekCompleteListener, like this :
mVideoView.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setOnSeekCompleteListener(new OnSeekCompleteListener() {
#Override
public void onSeekComplete(MediaPlayer mp) {
//TODO: Your code here
}
});
}
});
public class ObservableVideoView extends VideoView
{
private IVideoViewActionListener mVideoViewListener;
private boolean mIsOnPauseMode = false;
public interface IVideoViewActionListener
{
void onPause();
void onResume();
void onTimeBarSeekChanged(int currentTime);
}
public void setVideoViewListener(IVideoViewActionListener listener)
{
mVideoViewListener = listener;
}
#Override
public void pause()
{
super.pause();
if (mVideoViewListener != null)
{
mVideoViewListener.onPause();
}
mIsOnPauseMode = true;
}
#Override
public void start()
{
super.start();
if (mIsOnPauseMode)
{
if (mVideoViewListener != null)
{
mVideoViewListener.onResume();
}
mIsOnPauseMode = false;
}
}
#Override
public void seekTo(int msec)
{
super.seekTo(msec);
if (mVideoViewListener != null)
{
mVideoViewListener.onTimeBarSeekChanged(msec);
}
}
public ObservableVideoView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ObservableVideoView(Context context)
{
super(context);
}
public ObservableVideoView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
}
you can listen for events like this:
public class VideoPlayerActivity extends Activity
{
public static final String VIDEO_URL = "VideoUrl";
private String path = "";
private ObservableVideoView mVideoView;
#Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.video_player_activity_layout);
mVideoView = (ObservableVideoView) findViewById(R.id.videoView1);
mVideoView.setMediaController(new MediaController(this));
mVideoView.setVideoViewListener(mVideoViewListener);
path = getIntent().getStringExtra(VIDEO_URL);
if (path == "")
{
Toast.makeText(this, "Please edit VideoViewDemo Activity, and set path" + " variable to your media file URL/path", Toast.LENGTH_LONG)
.show();
}
else
{
mVideoView.setVideoPath(path);
mVideoView.requestFocus();
mVideoView.start();
}
}
private IVideoViewActionListener mVideoViewListener = new IVideoViewActionListener()
{
#Override
public void onTimeBarSeekChanged(int currentTime)
{
//TODO what you want
}
#Override
public void onResume()
{
//TODO what you want
}
#Override
public void onPause()
{
//TODO what you want
}
};
}
Farhan, you are correct, onSeekCompleteListener is not supported by VideoView.
But you can copy and locally customize the VideoView class to add this support yourself.
I show how to do this in my answer to 7990784.