Media Controllers Not Showing Xamarin Android - android

Good day all,
Please i'm using videoview to play a local video file, and i attached the mediacontroller, video plays ok, but no matter the setting i use, the media controller doesn't show, when i touch the device screen:
My code below:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Preview);
this.Window.SetFlags(WindowManagerFlags.KeepScreenOn, WindowManagerFlags.KeepScreenOn);
videoView = FindViewById<VideoView>(Resource.Id.videoPreView);
mediaController = new MediaController(this, true);
mediaController.SetAnchorView(videoView);
videoView.SetMediaController(mediaController);
}
protected override void OnStart()
{
base.OnStart();
videoView.Prepared += OnVideoPlayerPrepared;
Play("MyVids/PreviewCourse.mp4");
}
protected override void OnStop()
{
base.OnStop();
videoView.Prepared -= OnVideoPlayerPrepared;
}
private void OnVideoPlayerPrepared(object sender, EventArgs e)
{
mediaController.SetAnchorView(videoView);
//show media controls for 3 seconds when video starts to play
mediaController.Show(3000);
}
And this is my axml file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<VideoView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/videoPreView"
android:layout_centerInParent="true" />
Note: My videos are 480 by 360 in dimension
Thanks for your help

Well eventually, i had to create the buttons for pause/play, forward, and rewind manually.
player.pause();
player.play();
player.SeekTo(CurrentPosition + 5000); //for forward 5 secs
player.SeekTo(CurrentPosition - 5000) //to rewind
Didn't know it was that easy
For those who want to create there's manually

Related

How to show that a smaller video file streams fasters than a bigger video file?

I have a simple video player app in Android that plays two videos given a URL. One a smaller mp4 file and the other one a bigger sized file. Basically, I want to show that the smaller mp4 buffers and plays faster simply because of it's smaller size and that more contents need to be downloaded. But I have problems showing this concept and what I did doesn't really work like that. I initialize the second player after the first one, and get the time to buffer 100% of the URL video and show it below each player. Apparently it doesn't show what I'm intending to prove.
What am I doing wrong here? What are ways to make it prove the concept?
Here is my simple code:
package com.example.videoplayer;
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.AttributeSet;
import android.widget.MediaController;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
public class MainActivity extends AppCompatActivity {
//https://dl5.webmfiles.org/video-h264.mkv
//https://s3.amazonaws.com/x265.org/video/BigBuckBunny_2000hevc.mp4
private static final String VIDEO_SAMPLE =
"https://dl5.webmfiles.org/video-h264.mkv";
private static final String VIDEO_SAMPLE2 =
"https://dl5.webmfiles.org/video-h265.mkv";
private VideoView vw1, vw2;
private TextView mBufferingTextView,mBufferingTextView2;
// Current playback position (in milliseconds).
private int mCurrentPosition = 0;
// Tag for the instance state bundle.
private static final String PLAYBACK_TIME = "play_time";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vw1 = findViewById(R.id.videoView1);
vw2 = findViewById(R.id.videoView2);
mBufferingTextView = findViewById(R.id.buffering_textview);
mBufferingTextView2 = findViewById(R.id.buffering_textview2);
if (savedInstanceState != null) {
mCurrentPosition = savedInstanceState.getInt(PLAYBACK_TIME);
}
// Set up the media controller widget and attach it to the video view.
// MediaController controller = new MediaController(vw1.getContext());
// controller.setMediaPlayer(vw1);
// vw1.setMediaController(controller);
}
#Override
protected void onStart() {
super.onStart();
// Load the media each time onStart() is called.
initializePlayer();
initializePlayer2();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onStop() {
super.onStop();
// Media playback takes a lot of resources, so everything should be
// stopped and released at this time.
// releasePlayer();
}
private void initializePlayer() {
// Show the "Buffering..." message while the video loads.
mBufferingTextView.setVisibility(VideoView.VISIBLE);
// Buffer and decode the video sample.
long t0 = System.currentTimeMillis();
Uri videoUri = Uri.parse(VIDEO_SAMPLE);
vw1.setVideoURI(videoUri);
// Listener for onPrepared() event (runs after the media is prepared).
vw1.setOnPreparedListener(
new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
// Hide buffering message.
// mBufferingTextView.setVisibility(VideoView.INVISIBLE);
// Restore saved position, if available.
// if (mCurrentPosition > 0) {
// vw1.seekTo(mCurrentPosition);
// } else {
// // Skipping to 1 shows the first frame of the video.
// vw1.seekTo(1);
// }
// Start playing!
vw1.start();
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
boolean buffered = false;
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
if(i==100 && !buffered) {
long t1 = System.currentTimeMillis();
mBufferingTextView.setText((t1 - t0) + ", " + i + " ");
buffered = true;
}
}
});
}
});
// Listener for onCompletion() event (runs after media has finished
// playing).
vw1.setOnCompletionListener(
new MediaPlayer.OnCompletionListener()
{
#Override
public void onCompletion (MediaPlayer mediaPlayer){
Toast.makeText(MainActivity.this,
"Completed",
Toast.LENGTH_SHORT).show();
// Return the video position to the start.
vw1.seekTo(0);
}
});
}
private void initializePlayer2() {
// Show the "Buffering..." message while the video loads.
mBufferingTextView2.setVisibility(VideoView.VISIBLE);
// Buffer and decode the video sample.
long t0 = System.currentTimeMillis();
Uri videoUri = Uri.parse(VIDEO_SAMPLE2);
vw2.setVideoURI(videoUri);
// Listener for onPrepared() event (runs after the media is prepared).
vw2.setOnPreparedListener(
new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
// Hide buffering message.
// mBufferingTextView.setVisibility(VideoView.INVISIBLE);
// Restore saved position, if available.
// if (mCurrentPosition > 0) {
// vw2.seekTo(mCurrentPosition);
// } else {
// // Skipping to 1 shows the first frame of the video.
// vw2.seekTo(1);
// }
// Start playing!
vw2.start();
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
boolean buffered = false;
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
if(i==100 && !buffered) {
long t1 = System.currentTimeMillis();
mBufferingTextView2.setText((t1 - t0) + ", " + i + " ");
buffered = true;
}
}
});
}
});
// Listener for onCompletion() event (runs after media has finished
// playing).
vw2.setOnCompletionListener(
new MediaPlayer.OnCompletionListener()
{
#Override
public void onCompletion (MediaPlayer mediaPlayer){
Toast.makeText(MainActivity.this,
"Completed",
Toast.LENGTH_SHORT).show();
// Return the video position to the start.
vw2.seekTo(0);
}
});
}
// Release all media-related resources. In a more complicated app this
// might involve unregistering listeners or releasing audio focus.
private void releasePlayer() {
vw1.stopPlayback();
}
}
And the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
>
<!-- adding VideoView to the layout -->
<VideoView
android:id="#+id/videoView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/buffering_textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Buffering..."
android:layout_margin="8dp"
android:textSize="18sp"
android:textStyle="bold"
/>
<VideoView
android:id="#+id/videoView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/buffering_textview2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Buffering..."
android:layout_margin="8dp"
android:textSize="18sp"
android:textStyle="bold"
/>
</LinearLayout>
I checked the 2 videos in your code: video 1 has a bitrate of 4 MBPS and video 2 is at 2 MBPS. (I tested both with https://ffprobe.a.video to get the bitrates).
If the tester is on Wi-Fi, and has 10 MBPS of network throughput, both videos will download and playback with no issue.
IDK how to throttle inside an Android app. If this app is just for demonstration purposes, set up a laptop with Charles Proxy to throttle the network, and connect the android device through the Charles Proxy.
Other ways to demonstrate: get a "really big" video. Like 20 (or 40 or 50) MBPS. Then create a 5 (or 10) MBPS version. Then you might see more buffering on a 'traditional' network connection without the throttling.
Note: One of your videos is h264, the other is h265. If you want to do an apples:apples, I'd recommend having both videos with exactly the same format - just to reduce the number of variables in the experiment.

Xamarin android : VideoView does not call SurfaceCreated

I'm struggling to play a video from Assets with a VideoView and a MediaPlayer.
Build version : android 6.0.1 Marshmallow API 23
Debug Device : NVIDIA SHIELD Tablet K1
The issue : my VideoView seems to not create a surface, since the function "SurfaceCreated" is never called during debug.
Actual result : when the activity is loaded, the screen is grey and I can hear the correct sound of the video.
Here is my code :
public class VideoTestActivity : Activity, MediaPlayer.IOnPreparedListener, ISurfaceHolderCallback
{
MediaPlayer player;
VideoView _myVideoView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.VideoTest);
player = new MediaPlayer();
_myVideoView = FindViewById<VideoView>(Resource.Id.video);
_myVideoView.Start();
_myVideoView.SetZOrderOnTop(true); // tried from Q&A, display a grey screen
var descriptor = Assets.OpenFd("video.mp4");// the data is correctly loaded
player.SetDataSource(descriptor.FileDescriptor, descriptor.StartOffset, descriptor.Length);
player.Prepare();
player.Start();
}
public void OnPrepared(MediaPlayer mp)
{
throw new NotImplementedException();
}
public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height)
{
throw new NotImplementedException();
}
public void SurfaceCreated(ISurfaceHolder holder)
{
player.SetDisplay(_myVideoView.Holder); // never called
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
throw new NotImplementedException();
}
}
And here is my axml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:p1="http://schemas.android.com/apk/res/android"
p1:minWidth="25px"
p1:minHeight="25px"
p1:layout_width="match_parent"
p1:layout_height="match_parent"
p1:id="#+id/relativeLayout1">
<VideoView
p1:layout_width="fill_parent"
p1:layout_height="fill_parent"
p1:id="#+id/video"/>
</RelativeLayout>
What I have tried/checked :
my VideoView has a widht/height different from 0
the descriptor is correctly loaded
SetZOrderOnTop() has been called after Start()
the videoView is correctly loaded by FindViewById()
I'm still searching for an anwser, but since I have checked every post-related on stackOverflow, I opened this post.
Thanks for your time and knowledge.
Ok so finally i found a solution to play my video, but none to load the Surface.
Creating a raw folder was the solution.
here is the new code (other fields from the previous one are blank):
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.VideoTest);
VideoView view = (VideoView)FindViewById(Resource.Id.videoPacificRim);
String path = "android.resource://" + PackageName + "/" + Resource.Raw.pacificrim_file;
view.SetVideoURI(Android.Net.Uri.Parse(path));
view.Start();
}
I close the subject, even if the original question is not answered.

How to Set android video width and height

i have issues in android video playing. am geting videos from server and set to videoview but videos is playing in backgroung am not able to see that videos ,please refer my code what i have tried.
XML FILE
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<VideoView
android:id="#+id/eventDetailsPage_videosView"
android:layout_width="160dp"
android:layout_height="100dp"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:background="#drawable/ic_eventvideo_image" />
</LinearLayout>
Java Class
Uri uri=Uri.parse(mEventDetailsUtil1.getAttachmentsUrls().get(0).getAttach_url());
VideoView mVideosView = (VideoView) findViewById(R.id.eventDetailsPage_videosView);
MediaController mc = new MediaController(this);
mc.setAnchorView(mVideosView);
mc.setMediaPlayer(mVideosView);
mVideosView.setMediaController(mc);
mVideosView.setVideoURI(uri);
mVideosView.requestFocus();
mVideosView.start();
the video is playing when opening the activity , but i don't want like that i need when i click on VideoView i need to open video full screen.
Try this :
VideoView mVideoview;
mVideoview = (VideoView) findViewById(R.id.VideoView);
mPlayServer = (Button) findViewById(R.id.mServerbutton);
mPlayServer.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
playVideo(SERVER_VIDEO_URL);
}
});
private void playVideo(SERVER_VIDEO_URL)
try {
// Start the MediaController
MediaController mediacontroller = new MediaController(mContext);
mediacontroller.setAnchorView(mVideoview);
// Get the URL from String VideoURL
mVideo = Uri.parse(SERVER_VIDEO_URL);
mVideoview.setMediaController(mediacontroller);
mVideoview.setVideoURI(mVideo);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
mVideoview.requestFocus();
mVideoview.setOnPreparedListener(new OnPreparedListener() {
// Close the progress bar and play the video
public void onPrepared(MediaPlayer mp) {
mVideoview.start();
}
});
mVideoview.setOnCompletionListener(new OnCompletionListener() {
// Called when video is completed
public void onCompletion(MediaPlayer mp) {
}
});
}
To show in fullscreen use video view in new xml file with height and width as fill parent and start new activity with Intent.
Hope this helps.
Android does not support the resizing of videos, you may want to look into a Third Party library that you can utilize. By default android does not have this. I got the same problem while applying controls to video player.

How to set the preview image in videoview before playing

I created an VideoView in my activity, below is the code.
VideoView vvVideos = (VideoView) rootView.findViewById(R.id.videoView);
MediaController mediacontroller = new MediaController(ctx);
mediacontroller.setAnchorView(vvVideos);
Uri video = Uri.parse("android.resource://" + packageName +"/"+R.raw.sample);
vvVideos.setMediaController(mediacontroller);
LayoutParams params=vvVideos.getLayoutParams();
params.height=150;
vvVideos.setLayoutParams(params);
vvVideos.setVideoURI(video);
vvVideos.requestFocus();
vvVideos.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
vvVideos.start();
}
});
Now the video gets started to play when the activity gets created. I want to make my activity as follows
Video should not play when the activity gets open.
It shoud display the starting video image(currently its displaying black color)
It should play only when the user click on the video.
please help me.
Use seekTo( 1 ) to show the first frame.
Ensure the movie is paused and then use seekTo() to show the first frame of the video:
VideoView mVideoView = (VideoView) findViewById( R.id.video_preview );
mVideoView.setVideoURI( yourVideoPath );
mVideoView.seekTo( 1 ); // 1 millisecond (0.001 s) into the clip.
NOTE: We use .seekTo( 1 ) because setting .seekTo( 0 ) did not work on Android 9.
To have it play when clicked on has been answered by #Lingviston in another answer.
Create video thumbnail using this
Bitmap thumb = ThumbnailUtils.createVideoThumbnail("file path/url",
MediaStore.Images.Thumbnails.MINI_KIND);
and set to videoview
BitmapDrawable bitmapDrawable = new BitmapDrawable(thumb);
mVideoView.setBackgroundDrawable(bitmapDrawable);
1) Remove your onPrepareListener. I don't know why your video is starting playing after activity creation but onPrepareListener is called after videoView.start().
2) Add an ImageView widget into you layout on top of VideoView. Then set another onPrepareListener like this:
vvVideos.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
previewImage.setVisibility(View.GONE);
}
});
I've noticed that onPreparedListener fires too early, so you can use
new Handler().postDelay(Runnable, timeInMilis)
to dismiss preview image.
3) Add OnTouchListener with any gesture detection to you VideoView. Here is an example of what I'm using now:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
mGestureDetector = new GestureDetector(this, mGestureListener);
((VideoView) findViewById(R.id.activity_video_videoview)).setOnTouchListener(mTouchListener);
}
private OnTouchListener mTouchListener = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return true;
}
};
private SimpleOnGestureListener mGestureListener = new SimpleOnGestureListener() {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if(mVideoView.isPlaying())
mVideoView.pause();
else
mVideoView.start();
return true;
};
};
It starts/stops playing by a tap.
just seek video to 100 milliseconds it shows thumbnail using seekTo() method
videoView.seekTo(100);
You can do it with Glide 4.x. It will fetch the first frame of your video show it in an ImageView
add to your build.gradle
implementation 'com.github.bumptech.glide:glide:4.x.x'
and in your Class
GlideApp.with(context)
.load("your video URL")
.into(videoImageView);;
Thought I'd share my solution. The seekTo method works great but only for some devices. Here is my work around. I handle this in the onPrepared method for the onPreparedListener but its up to you.
#Override
public void onPrepared(MediaPlayer mp) {
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(uri.getPath());
try {
Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(currentPosition);
videoView.setBackgroundDrawable(new BitmapDrawable(bitmap));
} catch (OutOfMemoryError outOfMemoryError) {
//Not entirely sure if this will ever be thrown but better safe than sorry.
videoView.seekTo(currentPosition);
}
}
Now when you play the video you will need to remove this background image like so:
private void play() {
...
videoView.setBackgroundDrawable(null);
..
}
Enjoy!
I know it's an old question, but I needed the same solution and couldn't find the answer anywhere else so I did the solution and I'm sharing the love here:
I just created a little class for it:
public class LoadFirstVideoFrame implements Runnable {
private static Handler uiHandler = new Handler(Looper.getMainLooper());
private VideoView videoView;
private LoadFirstVideoFrame(VideoView videoView) {
this.videoView = videoView;
videoView.start();
videoView.resume();
uiHandler.post(this);
}
public void stop() {
videoView = null;
uiHandler.removeCallbacks(this);
}
#Override public void run() {
if (videoView == null) return;
if (videoView.isPlaying()) {
videoView.pause();
videoView.seekTo(0);
videoView = null;
} else {
uiHandler.post(this);
}
}
}
it simply asks to start playing and pauses the video back on the first frame as soon as it's actually playing (meaning it loaded the file and it's already rendering it on the SurfaceView).
The important note here is to remember to call stop() on this class so it can properly clean up and not memory leak anything.
I hope it helps.
I Have Created A ImageView For Thumbnail Like This
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:clickable="true"
android:focusable="true">
<VideoView
android:id="#+id/video_view"
android:layout_width="match_parent"
android:layout_height="220dp"/>
<ImageView
android:id="#+id/videoView_thumbnail"
android:layout_width="match_parent"
android:layout_height="220dp"
android:scaleType="centerCrop"/>
</RelativeLayout>
And Add setOnPreparedListener and setOnCompletionListener in Java Like This Way
VideoView videoView = (VideoView) view.findViewById(R.id.video_view);
ImageView thumbnailView=(ImageView)view.findViewById(R.id.videoView_thumbnail);
Glide.with(getApplicationContext()).load(your_Image_Path).into(thumbnailView);
//you can add progress dialog here until video is start playing;
mediaController= new MediaController(getContext());
mediaController.setAnchorView(videoView);
videoView.setMediaController(mediaController);
videoView.setKeepScreenOn(true);
videoView.setVideoPath(your_video_path);
videoView.start(); //call this method for auto playing video
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
thumbnailView.setVisibility(View.GONE);
//you can Hide progress dialog here when video is start playing;
}
});
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
videoView.stopPlayback();
thumbnailView.setVisibility(View.VISIBLE);
}
});
It Works For Me Very Well I Hope Its Usfull For All
very simple !!!
you can use glide library.
first add an imageView on videoView and use the code below:
GlideApp.with(getApplicationContext()).load("empty")
.thumbnail(GlideApp.with(getApplicationContext()).load("videoURL"))
.into(imageView);
this code will download an image, and eventually, that leads to less internet consumption.
You can use a #Joshua Pinter's answer to solve the problem. But I want to give you more suggestion about it. You yourself answer that seekTo(100) works instead of seekTo(1). Neither of the two ways is perfect. That is because seekTo(1) would get a black image and the seekTo(100) may got an exception.
I prefer to do like this:
// calculate the during time of the media
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
long time = mediaPlayer.getDuration();
// use a proper number
mVideoView.seekTo(time/2);
If you don't have the backend server, it may be better. Or, if you had a backend server, you can try it in this way.
The thumbnail is calculate by the server, the client just display the image which the backend response. And when it come to server side, you can do a lot of things.
Which picture is better? What if the picture is black too?
Should the server side generate it? Or should the server side just cache the picture of the media?
If you want to discuss more about the two questions we can discuss them later.
Add this in your xml
`<RelativeLayout
android:layout_width="match_parent"
android:layout_height="#dimen/dimen180"
android:background="#color/color_bg">
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/epPlayer"
android:layout_width="match_parent"
android:visibility="gone"
android:layout_height="match_parent"/>
<FrameLayout
android:id="#+id/flTv"
android:layout_width="match_parent"
android:background="#color/color_bg"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/ivTv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/tv"/>
</FrameLayout>
<ProgressBar
android:id="#+id/pbVideoView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_centerInParent="true"
android:indeterminate="true" />
</RelativeLayout>
`
for kotlin users
declare variable
private var simpleExoPlayer: ExoPlayer? = null
use this
simpleExoPlayer = SimpleExoPlayer.Builder(this).build()
epPlayer.player = simpleExoPlayer
val dataSourceFactory = DefaultDataSourceFactory(
this,
Util.getUserAgent(this, getString(R.string.app_name))
)
val videoSource = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(it1))
simpleExoPlayer!!.prepare(videoSource)
simpleExoPlayer!!.playWhenReady = true
simpleExoPlayer!!.addListener(object : Player.EventListener{
override fun onPlayerStateChanged(
playWhenReady: Boolean,
playbackState: Int
) {
if(playbackState== Player.STATE_READY)
{
pbVideoView.visibility= View.GONE
epPlayer.visibility= View.VISIBLE
flTv.visibility= View.GONE
}
if (playbackState== Player.STATE_BUFFERING)
{
pbVideoView.visibility= View.VISIBLE
}
}
})
I hope it helps.
To make your video stop playing when the activity starts just remove the video.start() method.

Android VideoView black screen

I have been looking for a way to get rid of the nasty black initial screen on a VideoView before the start() method is run.
I have tried with background image on the widget but it doesn't work as expected at all.
I have also tried putting an image of the first frame in the video on top of the VideoView and hiding it after the start() method.
Adding an onPrepared listener to start the video and then hide the image. This works but there is a horrible flicker in the transition and I don't know how to get rid of it.
Adding the MediaController had no effect at all. The problem persists (I still see the black flicker) and I don't want to have the video controls visible at all.
My code looks like this:
VideoView vSurface= (VideoView) findViewById(R.id.surfaceView1);
vSurface.setVideoURI(Uri.parse("android.resource://com.mypackage/" + R.raw.video1));
vSurface.setVisibility(View.VISIBLE);
vSurface.setOnPreparedListener(this);
vSurface.setDrawingCacheEnabled(true);
vSurface.setOnErrorListener(this);
I meet the same problem, and solve it with the accepted solution above plus this:
#Override
public void onPrepared(MediaPlayer mp) {
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
Log.d(TAG, "onInfo, what = " + what);
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
// video started; hide the placeholder.
placeholder.setVisibility(View.GONE);
return true;
}
return false;
}
});
I think onPrepared just means the video is ready to play, but not means video started playing. If hide placeholder in onPrepared, the screen still show a black screen.
On my Note3 and Nexus, this solution works well.
I had the same problem on Galaxy tab 2, Android 4.1.1.
Do videoView.setZOrderOnTop(true); and next videoView.start()
It works fine for me.
I got the same problem and i found a solution. Its a little bit hacky but it do the trick.
So basically you need to put your VideoView into a FrameLayout.
Over the videoview you need to add another FrameLayout with the background of your video and when your video is loaded and ready to play you hide the placeholder.
<FrameLayout
android:id="#+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_marginTop="50dip" >
<VideoView
android:id="#+id/geoloc_anim"
android:layout_width="fill_parent"
android:layout_height="172dip" android:layout_gravity="top|center" android:visibility="visible"/>
<FrameLayout
android:id="#+id/placeholder"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:background="#drawable/fondvert_anim">
</FrameLayout>
In your activity you need to implements OnPreparedListener and add this
//Called when the video is ready to play
public void onPrepared(MediaPlayer mp) {
View placeholder = (View) findViewById(R.id.placeholder);
placeholder.setVisibility(View.GONE);
}
So when the video is ready we hide our placeholder and that trick avoid the black flicker screen.
Hope this help someone.
I had same problem and this has worked for me ..
When you want to show video, make videoView.setZOrderOnTop(false); and when you want to hide video, just make videoView.setZOrderOnTop(true);
I 've got same problem I just used videov.setBackgroundColor(Color.WHITE) and then onprepare i used Color.TRANSPARENT) white is still better than black for me
None of the Above worked for me.
In my case, onPrepared gets called BEFORE the black frame went away, so I would still see the black frame.
I needed a solution where the video appeared shortly after the first frame.
So what I did was set the VideoView alpha to 0 in xml:
android:alpha="0"
and then before I start the video I animate the alpha back to 1:
videoView.animate().alpha(1);
videoView.seekTo(0);
videoView.start();
alternatively, you can just post a delayed Runnable to set the alpha to 1, instead of animating it.
By extending a TextureView, I get no black screens in the beginning or end. This is if you want to avoid using ZOrderOnTop(true).
public class MyVideoView extends TextureView implements TextureView.SurfaceTextureListener {
private MediaPlayer mMediaPlayer;
private Uri mSource;
private MediaPlayer.OnCompletionListener mCompletionListener;
private boolean isLooping = false;
public MyVideoView(Context context) {
this(context, null, 0);
}
public MyVideoView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setSurfaceTextureListener(this);
}
public void setSource(Uri source) {
mSource = source;
}
public void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) {
mCompletionListener = listener;
}
public void setLooping(boolean looping) {
isLooping = looping;
}
#Override
protected void onDetachedFromWindow() {
// release resources on detach
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
super.onDetachedFromWindow();
}
/*
* TextureView.SurfaceTextureListener
*/
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
Surface surface = new Surface(surfaceTexture);
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setLooping(isLooping);
mMediaPlayer.setDataSource(getContext(), mSource);
mMediaPlayer.setSurface(surface);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
mMediaPlayer.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
surface.release();
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
}
This worked for me:
videoView.setBackgroundColor(Color.WHITE); // Your color.
videoView.start();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
videoView.setBackgroundColor(Color.TRANSPARENT);
}
});
At least two years later, but I hope that was helpful.
This is definitely hacky, but better than overlaying an image (IMO).
boolean mRestored = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRestored = savedInstanceState != null;
}
#Override
public void onPrepared(MediaPlayer mp) {
if (!mRestored) vSurface.seekTo(1);
}
Assuming you are putting things into savedInstanceState in onSaveInstanceState.
Just show a frame from the video as preview.
vSurface.SeekTo(100);
Just use VideoView#setBackgroundDrawable(), I think.
initial settings.
VideoView.setBackgroundDrawable(yourdrawableid);
start video
VideoView.start();
VideoView.setBackgroundDrawable(0);
For people still looking for answer for this, calling VideoView.start() and VideoView.pause() in succession inside onPrepared worked for me. I know this may not be the ideal way of achieving this however it might be the one with minimal workaround required in the code. Hope this works for you too.
#Override
public void onPrepared(MediaPlayer mp) {
mVideoView.start();
mVideoView.pause();
}
This one works for me :
In XML : VideoView hide behind a Relative layout with white Background
<VideoView
android:id="#+id/myVideo"
android:layout_below="#+id/logo_top"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
/>
<RelativeLayout
android:id="#+id/mask"
android:background="#FFFFFF"
android:layout_below="#+id/logo_top"
android:layout_centerHorizontal="true"
android:layout_width="200dp" android:layout_height="200dp"
>
</RelativeLayout>
and in Activity : onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.acceuil);
myVideo = (VideoView) findViewById(R.id.myVideo);
mask = (RelativeLayout) findViewById(R.id.mask);
String path = "android.resource://"
+ getPackageName() + "/" + R.raw.anim_normal;
myVideo.setVideoURI(Uri.parse(path));
myVideo.start();
}
onStart :
public void onStart() {
final long time = System.currentTimeMillis();
super.onStart();
new CountDownTimer(5000, 100) {
#Override
public void onTick(long l) {
long time2 = System.currentTimeMillis();
if((time2 - time) > 500) {
mask.setVisibility(View.GONE);
}
}
}.start();
Hope this helps.
For me setting the setZOrderOnTop did not completely remove the initial black frame while playing an mp4 video. It, however, did reduce the time for which the black frame appears. I wanted to remove the initial black frame completely, so I played around and found that seeking the video forward by 100ms did the trick for me.
As a note, I am using the video in a loop, so if you do not want to loop the video just remove
mp.isLooping = true
Following is the snippet which I used to fix the issue:
val path = "android.resource://" + packageName + "/" + R.raw.my_video
videoView.setVideoURI(Uri.parse(path))
videoView.setZOrderOnTop(true)
videoView.seekTo(100)
videoView.start()
videoView.setOnPreparedListener { mp ->
videoView.setZOrderOnTop(false)
mp.isLooping = true // Loops the video
}
It would still be great if I get an exact explanation of why the above worked if someone finds it helpful.
Use svVideoView.seekTo(position).
Give Position within 5 (ms).
onPause():
position=svVideoView.getCurrentPosition()
onResume():
svVideoView.seekTo(position);
It works for me on both Activity and Fragment.
VideoView mVideo = (VideoView) findViewById(R.id.yourViewViewId);
mVideo.setVideoURI(mUri);
mVideo.setZOrderOnTop(false);
SurfaceHolder surfaceholder = mVideo.getHolder();
surfaceholder.setFormat(PixelFormat.TRANSPARENT);
It's a little late for this answer, but maybe other users have the same problem and find this question..
I have dealt with it, by setting a BackgroundResource initially and then, when starting the video, i have set the background to an invisible color..
VideoView myView = findViewById(R.id.my_view);
myView.setBackgroundResource(R.drawable.some_resource);
// some stuff
// this is when starting the video
myView.setVideoUri(someUri);
// also set MediaController somewhere...
//...
// now set the backgroundcolor to be not visible (first val of Color.argb(..) is the alpha)
myView.setBackGroundColor(Color.argb(0, 0, 0, 0));
//...
myView.start();
This is a nice solution:
package com.example.videoviewpractice;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.MediaController;
import android.widget.VideoView;
public class MainActivity extends Activity {
VideoView myVideoView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initVideo();
}
private void initVideo() {
myVideoView = (VideoView) findViewById(R.id.videoView1);
String url = "http://mtc.cdn.vine.co/r/videos/3DF00EB7001110633055418310656_1e50d6d9a65.3.2.mp4?" +
"versionId=KVMUFFGqe6rYRrGKgl8hxL6eakVAErPy";
myVideoView.setVideoURI(Uri.parse(url));
myVideoView.setMediaController(new MediaController(this));
myVideoView.requestFocus();
}
public void gone(View v){
myVideoView.setZOrderOnTop(true);
View placeholder = (View) findViewById(R.id.placeholder);
placeholder.setVisibility(View.GONE);
myVideoView.start();
}
}
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >
<FrameLayout
android:id="#+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_marginTop="50dip" >
<VideoView
android:id="#+id/videoView1"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="top|center"
android:visibility="visible" />
<FrameLayout
android:id="#+id/placeholder"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="top|center"
android:background="#drawable/ic_launcher"
android:onClick="gone" >
</FrameLayout>
</FrameLayout>
</LinearLayout>
To avoid annoying flickering and black screen issues I wrote FrameVideoView.
It takes benefits from 'placeholder solution' and (if your device is running API level 14 or higher) from TextureView, which is much more efficient than VideoView.
I wrote article on our blog to cover what it actually does.
It's simple to use:
Add FrameVideoView to layout:
<mateuszklimek.framevideoview.FrameVideoView
android:id="#+id/frame_video_view"
android:layout_width="#dimen/video_width"
android:layout_height="#dimen/video_height"
/>
find its instance in Activity and call corresponding methods in onResume and onPause:
public class SampleActivity extends Activity {
private FrameVideoView videoView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple);
String uriString = "android.resource://" + getPackageName() + "/" + R.raw.movie;
videoView = (FrameVideoView) findViewById(R.id.frame_video_view);
videoView.setup(Uri.parse(uriString), Color.GREEN);
}
#Override
protected void onResume() {
super.onResume();
videoView.onResume();
}
#Override
protected void onPause() {
videoView.onPause();
super.onPause();
}
}
I had the same issue. I found that the main reason for that was the use of FrameLayout as the parent layout. Use RelativeLayout as the parent layout of the VideoView
Modifying #emmgfx's answer worked for me:
videoView.setBackgroundColor(Color.WHITE)
videoView.start()
Timer().schedule(100){
videoView?.setBackgroundColor(Color.TRANSPARENT)
}
Trick is to delay the video view untill video loads.
PS : It's kotlin.
I found a great solution to this problem. ( in Kotlin )
Create an imageview over top of your videoview.
Create a function with a handler, and check if ( videoview.duration > 0 )
if the duration is greater than zero, then set the imageview.visibility to INVISABLE, and immediately follow by handler.removeCallbacks(this)
Call the above function after you have called videoview.start
Code below:
fun showVideoView() {
val handler = Handler()
handler.postDelayed(object : Runnable {
override fun run() {
try {
if (videoplayer_topthree.currentPosition > 0) {
videoview_topthreeloadingimage.visibility = View.INVISIBLE
videoview_topthreeprogressbar.visibility = View.VISIBLE
videoview_topthreefullname.visibility = View.VISIBLE
videoview_topthreeviews.visibility = View.VISIBLE
videoview_topthreedate.visibility = View.VISIBLE
videoview_topthreedescription.visibility = View.VISIBLE
videoview_topthreedimview.visibility = View.VISIBLE
handler.removeCallbacks(this)
}
handler.postDelayed(this, 250)
} catch (e: Exception) {
println("SHOW VIDEOVIEW CATCH WAS CAUGHT")
}
}
}, 0)
}
and this is where I call this function..
videoplayer_topthree.setOnPreparedListener {
prepareSizing(it)
initializeProgressBar()
showVideoView()
}
Trying to play a mostly white video on a mostly white layout shows these glitches in a very obvious and annoying way, particularly during Activity transitions. The only way I managed to completely get rid of the glitches was to mash together a few different answers from this thread and elprl's answer at https://stackoverflow.com/a/9089245/3997253.
Create a solid colour View that covers the VideoView
<View
android:id="#+id/coverView"
android:background="#color/white"
android:layout_width="match_parent"
android:layout_height="match_parent" />
In onCreate
...
coverView = findViewById(R.id.coverView)
videoView = findViewById(R.id.videoView)
videoView.setZOrderOnTop(false)
val surfaceHolder = videoView.holder
surfaceHolder.setFormat(PixelFormat.TRANSPARENT)
In onStart
...
videoView.setOnPreparedListener { mp ->
// Fade out cover View to show VideoView once rendering has started
mp.setOnInfoListener { _, what, _ ->
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
coverView.animate().alpha(0F)
return#setOnInfoListener true
}
return#setOnInfoListener false
}
mp.isLooping = true
videoView.start()
videoView.requestFocus()
}
When done with the VideoView
// Fade in cover View to hide the VideoView
coverView.animate().alpha(1F)
Only this worked for me:
fun VideoView.startWithRawFile(rawFileResId: Int, delay: Long = 0, backgroundColorResId: Int = R.color.white) {
setBackgroundResource(backgroundColorResId)
setVideoURI(uriToRawFile(rawFileResId))
setOnPreparedListener {
postDelayed(delay) {
start()
// replace 200 with your value according to your video file content:
postDelayed(200) { setBackgroundResource(R.color.transparent) }
}
}
}
// additional:
fun uriToRawFile(rawFileResId: Int) = Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE).authority(app().packageName).appendPath("$rawFileResId").build()
fun postDelayed(ms: Long, runnable: () -> Unit) = if (ms > 0) Handler(Looper.getMainLooper()).postDelayed(runnable, ms)
else runnable.invoke()
see this
VideoView videoView = (VideoView) findViewById(R.id.VideoView);
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(videoView);
Uri video = Uri.parse("android.resource://your_package_name/"+R.raw.monkeysonthebed_video);
videoView.setMediaController(mediaController);
videoView.setVideoURI(video);
videoView.start();

Categories

Resources