locked
Android Video Player using Xamarin.Forms RRS feed

  • Question

  • User53292 posted

    I am trying to get a video player working in my Xamarin.Forms app on Android. I have implemented the iOS version using a ScrollViewRenderer where I add the MPMoviePlayerController (code at bottom, file attach not working). For Android, I consulted the library for playing a video in straight Android (http://developer.xamarin.com/recipes/android/media/video/play_video/), and attempted two different tacks: - create the VideoView and add it using AddView on the renderer itself, or the inside horizontal scrollview - use the PageRenderer, create the XAML from the video recipe, use this.Context as Activity, and SetContentView to the XAML.

    Needless to say, both versions failed, leaving just a blank screen.

    Does anyone have a sample that is working in .Forms, or ideas for other approaches I might attempt? Nearing the end of my rope here.

    Thanks...


    public class VideoScrollViewRenderer : ScrollViewRenderer { protected override void OnElementChanged (VisualElementChangedEventArgs e) { base.OnElementChanged (e);

            if (e.OldElement == null) 
            {
                VideoScrollView thisView = (VideoScrollView)Element;
    
                RectangleF dispRect = new RectangleF (0, 0, (float)thisView.ParentView.Width,(float)thisView.ParentView.Height);
    
                var view = GetView (dispRect);
    
                ShowMovie (thisView.videoName, view);
            }
        }
    
        UIView GetView (RectangleF dispRect)
        {
            var view = NativeView;
            view.Bounds = dispRect;
            return view;
        }
    
        static void ShowMovie (string videoName, UIView view)
        {
            string fileDir = string.Format ("video/{0}", videoName);
            string localDocUrl = Path.Combine (NSBundle.MainBundle.BundlePath, fileDir);
            var moviePlayer = new MPMoviePlayerController (new NSUrl (localDocUrl, false));
            moviePlayer.View.Frame = view.Bounds;
            view.Add (moviePlayer.View);
            moviePlayer.Play ();
        }
    }
    
    Thursday, September 11, 2014 8:11 PM

All replies

  • User2496 posted

    I have worked on this in one app, i showed this view. it's a draft control.. does it job but very simple, heres how i do it:

    <localControls:VideoView FileSource="video.mp4" Grid.RowSpan="2" x:Name="video"></localControls:VideoView>

    Control:

             public class VideoView : View
                {
                    public Action StopAction;
                    public VideoView ()
                    {
    
                    }
    
            public static readonly BindableProperty FileSourceProperty = 
                BindableProperty.Create<VideoView,string>(
                    p => p.FileSource,string.Empty);
    
            public string FileSource {
                get { return (string)GetValue (FileSourceProperty); }
                set { SetValue (FileSourceProperty, value); }
            }
    
            public void Stop(){
                if(StopAction != null)
                    StopAction ();
            }
        }
    

    Android renderer:

        public class VideoViewRenderer : ViewRenderer<Shair.Controls.VideoView,VideoView>, ISurfaceHolderCallback
        {
            public VideoViewRenderer ()
            {
            }
    
            public void SurfaceChanged (ISurfaceHolder holder, global::Android.Graphics.Format format, int width, int height)
            {
    
            }
    
            public void SurfaceDestroyed (ISurfaceHolder holder)
            {
    
            }
    
            protected override void OnElementChanged (ElementChangedEventArgs<Shair.Controls.VideoView> e)
            {
                base.OnElementChanged (e);
                e.NewElement.StopAction = () => {
                this.player.Stop();
                    this.Control.StopPlayback ();
                };
    
                videoview = new VideoView (Context);
    
                base.SetNativeControl (videoview);
                Control.Holder.AddCallback (this);
                player = new MediaPlayer();
                play (e.NewElement.FileSource);
    
            }
            VideoView videoview;
            MediaPlayer player;
            void play(string fullPath)
            { 
                AssetFileDescriptor afd = Forms.Context.Assets.OpenFd(fullPath);
                if (afd != null)
                {
                    player.SetDataSource(afd.FileDescriptor, afd.StartOffset, afd.Length);
                    player.Prepare ();
                    player.Start();
                    Control.Layout (0, 200, player.VideoHeight, player.VideoWidth);
    
                }
            }
    
            public void SurfaceCreated (ISurfaceHolder holder)
            {
                 player.SetDisplay(holder);
            }
        }
    

    IOS renderer:

     public class VideoViewRenderer : ViewRenderer<VideoView,UIVideoView>
        {
            protected override void OnElementChanged (ElementChangedEventArgs<VideoView> e)
            {
                base.OnElementChanged (e);
                e.NewElement.StopAction = () => {
                    this.Control.Stop ();
                };
                base.SetNativeControl (new UIVideoView (e.NewElement.FileSource,UIScreen.MainScreen.Bounds));
            }
        }
    
    public class UIVideoView : UIView
        {
            bool _isPlaying = false;
            MPMoviePlayerController moviePlayer;
            public UIVideoView (string file, RectangleF frame)
            {
    
                this.AutoresizingMask = UIViewAutoresizing.All;
                this.ContentMode = UIViewContentMode.ScaleToFill;
    
                moviePlayer = new MPMoviePlayerController (NSUrl.FromFilename (file));
                moviePlayer.View.ContentMode = UIViewContentMode.ScaleToFill;
                moviePlayer.View.AutoresizingMask = UIViewAutoresizing.All;
                moviePlayer.RepeatMode = MPMovieRepeatMode.One;
                moviePlayer.ControlStyle = MPMovieControlStyle.None;
                moviePlayer.ScalingMode = MPMovieScalingMode.AspectFit;
                this.Frame  = moviePlayer.View.Frame =  frame;
                Add(moviePlayer.View);
                moviePlayer.SetFullscreen (true, true);
                moviePlayer.Play ();
                _isPlaying = true;
            }
    
            public void Stop(){
                if (_isPlaying)
                    moviePlayer.Stop ();
    
            }
        }
    
    Thursday, September 11, 2014 10:50 PM
  • User72641 posted

    @rmarinho? I am trying to run the local video on Andriod by implementing the custom renderer code provided by you in the post above. I am still getting black screen though the renderer is called. Any suggestions?

    Friday, September 12, 2014 6:31 AM
  • User2496 posted

    Hum where is your video? and what build properties did u set to the video?1 can you debug and see if the renderer is being called ?

    Friday, September 12, 2014 10:23 AM
  • User71672 posted

    It works perfectly!

    Sunday, September 14, 2014 6:50 PM
  • User53292 posted

    @rmarinho? - Awesome, worked perfectly, thanks!

    Monday, September 15, 2014 1:58 PM
  • User72641 posted

    @rmarinho Video is in Asset folder in Andriod Project with build action as Andriod Asset. Yes the andriod renderer is being called. Please suggest.

    Tuesday, September 16, 2014 1:49 AM
  • User2496 posted

    You can move the video to the root of your android project and mark the file as AndroidAsset to see if it works.

    Tuesday, September 16, 2014 10:17 PM
  • User72641 posted

    @rmarinho? Thanks for your replies. I have done the change you suggested by moving video to root of project with other files and mark as AndriodAsset. Control goes to Play and Surface created Methods of renderer on debugging but still black screen. Not sure why its not working for me. Please suggest.

    Tuesday, September 16, 2014 10:52 PM
  • User80275 posted

    @rmarinho? I wanted to use your example to display Vimeo from the Uri but it didn't work. I have a View in my Shared Code and I want to render video in Android specific code to fit that View. Is it possible? Can you help me please?

    Regards

    Thursday, October 16, 2014 9:02 AM
  • User72641 posted

    @JefimijaPetkovic.2273? I wanted to do the same thing and found that when we give uri to run vimeo video, vimeo kind of put a wrapper around video so it doesnt work as android player is looking for actual video. Finally I end up showing the video image in my application view and on tap of that image I am opening the URI in browser using following code.

    Device.OpenUri(new Uri("vimeo video uri"))

    Thursday, October 16, 2014 9:44 PM
  • User80275 posted

    I have View in my shared code, and I am making custom renderer for video in Android specific code.

    I implemented it like this:

    [assembly: ExportRenderer(typeof(ESEC.Exploodo.ViewMobile.CustomRenderedViews.VimeoView), typeof(ESEC.Exploodo.ViewMobile.Droid.VimeoRenderer))]

    namespace ESEC.Exploodo.ViewMobile.Droid { public class VimeoRenderer : ViewRenderer, ISurfaceHolderCallback, MediaController.IMediaPlayerControl { //MediaPlayerControl public bool IsPlaying { get; set; }
    public int Duration { get { return player.Duration; }

        }
        public int CurrentPosition
        {
            get { return getCurrentPositionInt() / 1000; } 
           }
        public int BufferPercentage
        {
            get { return 0; }
    
        }
        public int AudioSessionId
        {
            get{ return player.AudioSessionId;}
    
        }
    
        public MediaPlayer player;
        public VideoView videoView;
        public CustomMediaController mediaController;
    
        //sources
        public string _mobileMp4Link;
    
        public VimeoRenderer() { }
    
        public void SurfaceChanged(ISurfaceHolder holder, global::Android.Graphics.Format format, int width, int height) { }        
        public void SurfaceDestroyed(ISurfaceHolder holder) { }
    
        protected override void OnElementChanged(ElementChangedEventArgs<VimeoView> e)
        {
            base.OnElementChanged(e);
    
            videoView = new VideoView(Forms.Context);
            mediaController = new CustomMediaController(Forms.Context, false);
    
    
            mediaController.SetAnchorView(videoView);
            mediaController.SetMinimumWidth(videoView.Width);
            mediaController.RequestFocus(); //will make it display as soon as the video starts                    
            videoView.SetMediaController(mediaController);
    
            videoView.Prepared += delegate
            {
                videoView.Start();
            };
    
            player = new MediaPlayer();
    
    
            base.SetNativeControl(videoView);
            Control.Holder.AddCallback(this);           
        }
    
        public void SurfaceCreated(ISurfaceHolder holder)
        {
            player.SetDisplay(holder);
    
            VimeoView helper = (VimeoView)this.Element;
            _mobileMp4Link = "http:" + helper.MobileMp4Link;
    
            player.SetDataSource(_mobileMp4Link);
    
            //player.Prepared += delegate
            //{                
            //    mediaController.SetMediaPlayer(this);
            //    mediaController.SetAnchorView(videoView);
            //    mediaController.SetPadding(0, 0, 0, 0);
            //    mediaController.Enabled = true;
            //    mediaController.SetMinimumWidth(videoView.Width);
            //    mediaController.RequestFocus();
            //    mediaController.Show(0); //will keep it on the screen
    
            //};           
            player.Prepare();
    
    
            player.Start();
            player.SeekTo((int)(getCurrentPositionInt() / 1000));
        }
    

    In order to be able to control Hide() and Show() methods (after interaction with controller it would disappear, so I wanted to avoid that), inherited my own controller from MediaController:

    public class CustomMediaController : MediaController
    {
        public CustomMediaController(Context context, bool b) : base(context, false) { }
    
        public override void Hide() { }       //this will make controller not to disappear after interaction
        public override void Show()
        {
            base.Show();
        }
    
    }
    

    } Hope that this will help someone. Regards

    Monday, October 20, 2014 10:39 AM
  • User94172 posted

    @rmarinho I have a question here.Can we show video in specific part of a form ? I am able to play video in xamarin forms but it takes a complete content page I am using this to reference my android video activity into empty form.

    [assembly: Xamarin.Forms.ExportRenderer (typeof (maVideoPlayer), typeof (VideoPlayerRenderer))]

    Wednesday, January 7, 2015 6:59 AM
  • User94172 posted

    @MarioLorente can you please help me out using this code ?

    Wednesday, January 7, 2015 8:58 AM
  • User73826 posted

    @rmarinho?

    Hi! Can you explain me the difference between Shair.Controls.VideoView and VideoView in this part of code?

    public class VideoViewRenderer : ViewRenderer<Shair.Controls.VideoView,VideoView>, ISurfaceHolderCallback

    I think it's the same type but when I try to compile for android I get this error: Error CS0311: The type 'MyApp.Controls.VideoView' cannot be used as type parameter 'TNativeView' in the generic type or method 'Xamarin.Forms.Platform.Android.ViewRenderer<TView,TNativeView>'. There is no implicit reference conversion from 'MyApp.Controls.VideoView' to 'Android.Views.View' (CS0311) (MyApp.Android)

    Please note: I'm not an expert...

    No issues with iOS.

    Thank you

    Thursday, January 8, 2015 4:50 AM
  • User94172 posted

    @rmarinho? Shair is your name space and Controls is the folder inside it. if you put the file in your root you need to write it like this

    public class VideoViewRenderer : ViewRenderer<YourNameSpace.VideoView,VideoView>, ISurfaceHolderCallback

    and if you include your namespace like this using YourNameSpace you need to jut write like this

    public class VideoViewRenderer : ViewRenderer<VideoView,VideoView>, ISurfaceHolderCallback

    Thursday, January 8, 2015 7:30 AM
  • User45048 posted

    I'm having an issue with the custom renderer outlined above; specifically, the Android renderer. The iOS renderer is working fine.

    Specifically, I cannot get the code to build. I have the error in the Android renderer listed above" Error CS0311: The type 'MyApp.Controls.VideoView' cannot be used as type parameter 'TNativeView' in the generic type ...

    I also don't seem to have access to either Control.Holder.AddCallback nor the Control.StopPlayback methods. Again, the iOS code seems to work fine but there are issues with the Android build. Any suggestions? It seems like I may not have access to the full native Android functionality - I've written an Android-only video player before but not using Forms.

    Thursday, January 8, 2015 7:56 PM
  • User73826 posted

    @AliAkram thank you. I imaged that shair was the namespace, but the question is still valid. Why is the whole path needed in the first VideoView but is not in the second one if I decide to not use 'using' statement? I expect something like: public class VideoViewRenderer : ViewRenderer<YourNameSpace.VideoView,YourNameSpace.VideoView>, ISurfaceHolderCallback or

    public class VideoViewRenderer : ViewRenderer<VideoView,VideoView>, ISurfaceHolderCallback

    I don't understand the hybrid way. In both cases the issue of TNativeView is the same.

    What's going wrong?

    @rmarinho Could you attach the whole solution of a working example? Thank you in advance

    EDIT: I understand now. Note for stupid people like me: the second VideoView is not referred to the our new control but is a native widget and you need to add the following statement: using Android.Widget; I decided to rename my control in "MyVideoView" to avoid confusion in future.

    using MyNamespace; using Android.Widget; ... public class MyVideoViewRenderer : ViewRenderer<MyVideoView,VideoView>, ISurfaceHolderCallback

    Friday, January 16, 2015 5:35 AM
  • User94172 posted

    @rmarinho? Can you please help me in this regard? I have a close deadline for this to deliver. I am trying to render video in xamarin forms.This example works fine but when application goes in pause state or in some other form page or i press home/power button surface is destroyed and nothing keeps on playing . Can anyone suggest me solution?

    Sunday, January 18, 2015 9:34 AM
  • User97319 posted

    @Tedebus I am one of those too. Thank you for the clarification! Finally have it compiling.

    Tuesday, January 20, 2015 2:50 AM
  • User73826 posted

    @FernandoAlvarez.5242? Well, that's good. But did you solve clip position matter? On iOs I'm able to show video including it in solution. On Android area remains blank...

    Tuesday, January 20, 2015 5:13 AM
  • User97794 posted

    Hi! I have a problem of positioning the video. I'm using CustomRenderer loading video for URL and playing it in videoView. My video is always stretched allover the screen even though the video is small 640x480. I've tried different layout parameters within the CustomRenderer, as well in the shared code but nothing chages. Can some help me about this? How can I set a proper videoview layout ?

    Sunday, February 15, 2015 9:15 PM
  • User73826 posted

    For those who are still trying to understand why it works on iOs but not with Android: remember that if you use [assembly: ExportRenderer(typeof(VideoView), typeof(VideoViewRenderer))] for the compiler the first VideoView is Android.Widget.VideoView and not your custom control. You won't see compile errors. It's better to use the whole path of classes: [assembly: ExportRenderer(typeof(mynamespace.VideoView), typeof(mynamespace.Android.VideoViewRenderer) On iOs this risk does not exist because VideoRender is not an iOs class, in fact on iOs the equivalent class is UIVideoView! Now it should work properly.

    Tuesday, February 17, 2015 2:14 AM
  • User106695 posted

    @JefimijaPetkovic, Thanks for sharing the android version of the code! I'm trying to do the same thing on iOS, but I'm seeing black screen when I give Vimeo url to the player. Can you share the iOS version of your code please?

    Thanks in advance!

    Tuesday, February 17, 2015 9:50 PM
  • User96735 posted

    sorry to say but i have following error Partial declarations of `Myexample1.VideoLists' must not specify different base classes (Myexample1.Droid)

    Saturday, March 14, 2015 1:37 PM
  • User49837 posted

    @Jefimijana I tried the way you described video is viewable but the mediacontroller is not displayed.When I call the mediacontroller.show() its throwing the Java.Lang.NullPointerException. even im checking whether the player is null or not.

    Please do needful

    Wednesday, March 25, 2015 12:28 PM
  • User49837 posted

    Hi all ,did anyone tried handling the Media Controller controls event handling.Please let me know the steps if so done.

    Thursday, March 26, 2015 11:56 AM
  • User77074 posted

    @rmarinho Is there any possibility to code renderer for window phone

    Tuesday, May 19, 2015 9:08 AM
  • User130382 posted

    how to add play/pause/stop buttons ?

    Tuesday, May 26, 2015 2:37 PM
  • User77074 posted

    @AniketSonsale In which platform 1) Android use CCMediaController 2)IOS MPMoviePlayerController gives you this buttons except stop 3)Winphone you have to handle your self using mediaelement

    Friday, May 29, 2015 6:46 AM
  • User130382 posted

    Thanks @JitendraPatel I am building using PCL ....

    Thursday, June 4, 2015 11:55 AM
  • User58581 posted

    @KanwarBadyal Did you solve your problem with just showing black screen on Android when using the code from rmarinho? I have the same issue. My control and renderer names are correct and there are even MediaPlayer logs that tell me the video exists and is playing. But just black screen... Tested on different devices. Any ideas?

    Thursday, July 9, 2015 9:39 AM
  • User151902 posted

    Hi,

    Media Controls are not able to see with the above android renderer code.can anyone post code for meadia controller able to show and pause and play to be working..

    Thanks

    Wednesday, September 16, 2015 11:17 AM
  • User151902 posted

    @Rui Marinho Hi Media Controller not working with the renderer for android .can you please post code to make meadia controls work i.e pause,play.seekto.

    Wednesday, September 16, 2015 11:21 AM
  • User141005 posted

    I have observed that the emulator shows a black screen even though the audio is playing. When I deploy the app to an actual test device (not an emulator), I can observe the video playing. However, I've noticed the aspect ratio being off on the video. Specifically, I observe the video images being stretched to fit the screen when the screen is showing in portrait mode. This makes viewing the video kind of strange.

    Tuesday, September 29, 2015 6:57 AM
  • User159322 posted

    For anyone still needing to get the MediaController to play... This code was taken from http://stackoverflow.com/questions/3747139/how-can-i-show-a-mediacontroller-while-playing-audio-in-android/5265629#5265629

    using System; using System.Collections.Generic; using System.Linq; using System.Text;

    using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using Xamarin.Forms; using YOURAPPNAME.Portable.Droid; using Xamarin.Forms.Platform.Android; using Android.Media; using Android.Content.Res; using Java.Lang;

    [assembly: ExportRenderer(typeof(YOURAPPNAME.VideoView), typeof(VideoViewRenderer))]

    namespace electronicApp.Portable.Droid { public class VideoViewRenderer : ViewRenderer, ISurfaceHolderCallback, MediaController.IMediaPlayerControl, MediaPlayer.IOnPreparedListener {

        VideoView videoview;
        MediaPlayer player;
        MediaController mediaController;
        Handler handler = new Handler();
        public VideoViewRenderer()
        {
        }
    
        public void SurfaceChanged(ISurfaceHolder holder, global::Android.Graphics.Format format, int width, int height)
        {
    
        }
    
        public void SurfaceDestroyed(ISurfaceHolder holder)
        {
    
        }
    
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
        }
    
        protected override void OnElementChanged(ElementChangedEventArgs<electronicApp.Portable.Controls.VideoView> e)
        {
            base.OnElementChanged(e);
            e.NewElement.StopAction = () =>
            {
                mediaController.Hide();
                player.Stop();
                player.Release();
            };
    
            e.NewElement.StartAction = () =>
            {
    
                this.player.Start();
            };
    
            e.NewElement.PauseAction = () =>
            {
    
                this.player.Pause();
                mediaController.Hide();
            };
    
            e.NewElement.HideAction = () =>
            {
                mediaController.Hide();
            };
    
    
            videoview = new VideoView(Context);
    
    
            base.SetNativeControl(videoview);
            Control.Holder.AddCallback(this);
            Control.SetZOrderMediaOverlay(true);
            player = new MediaPlayer();
    
            player.SetOnPreparedListener(this);
            mediaController = new MediaController(this.Context);
            play(e.NewElement.FileSource);
        }
    
        void play(string fullPath)
        {
            AssetFileDescriptor afd = Forms.Context.Assets.OpenFd(fullPath);
            if (afd != null)
            {
    
                player.SetDataSource(afd.FileDescriptor, afd.StartOffset, afd.Length);
                player.Prepare();
                player.Start();
                Control.Layout(0, 200, 400, 600);
                player.Pause();
    
    
            }
        }
    
        public override bool OnTouchEvent(MotionEvent e)
        {
            mediaController.Show();
            return false;
        }
    
        //--MediaPlayerControl methods----------------------------------------------------
        public void Start()
        {
            player.Start();
        }
    
    
        public void Pause()
        {
            player.Pause();
        }
    
        public int Duration
        {
            get
            {
                return player.Duration;
            }
        }
    
        public int CurrentPosition
        {
            get
            {
                return player.CurrentPosition;
            }
        }
    
        public void SeekTo(int i)
        {
            player.SeekTo(i);
        }
    
        public bool IsPlaying
        {
            get
            {
                return player.IsPlaying;
            }
        }
    
        public int BufferPercentage
        {
            get
            {
                return 0;
            }
        }
    
        public int AudioSessionId
        {
            get
            {
                return 0;
            }
        }
    
        public bool CanPause()
        {
            return true;
        }
    
        public bool CanSeekBackward()
        {
            return true;
        }
    
        public bool CanSeekForward()
        {
            return true;
        }
        //--------------------------------------------------------------------------------
    
        public void OnPrepared(MediaPlayer mediaPlayer)
        {
            mediaController.SetMediaPlayer(this);
            mediaController.SetAnchorView(videoview);
        }
    
    
        public void SurfaceCreated(ISurfaceHolder holder)
        {
            player.SetDisplay(holder);
        }
    }
    

    }

    Friday, October 9, 2015 3:17 PM
  • User37727 posted

    Black screen. Nothing appears, just black screen. OnPrepared is never called. Is there anybody who has it implemented successfully??

    Friday, October 23, 2015 8:16 AM
  • User171767 posted

    why do you handle only SurfaceCreated and not SurfaceChanged too? (and do player.SetDisplay(holder); and both). Also I'd expect at SurfaceDestroyed to do player.SetDisplay(null) or see if there's some player.ClearDisplay or ReleaseDisplay or similar instead.

    Thursday, November 5, 2015 1:37 PM
  • User52818 posted

    I get the video working BUT not the way I want to. I can only see the video if I put following line in my XAML file. I have to specify some Height- and WidthRequest otherwise nothing is showing. I can hear the sound though. I used @rmarinho s example:

    <local:WSVideoView FileSource="video.mp4" x:Name="wsVideoView" HeightRequest = "90" WidthRequest = "128"/>

    The following line in the code has no effect what so ever:

    Control.Layout (0, 200, player.VideoHeight, player.VideoWidth);

    Any ideas?

    Wednesday, November 25, 2015 2:08 PM
  • User52818 posted

    could anyone send me an example code of the XAML file to display the video with a filling screen and keeping the aspect ratio? My version always fills up the whole screen and distorts the video.

    Thursday, December 10, 2015 4:05 PM
  • User181025 posted

    I desperately need a video player. How come Xamarin has not provided one out of the box? We shouldn't have to spend days trying to get basic controls figured out.

    Tuesday, December 22, 2015 3:11 AM
  • User177387 posted

    Hi there, i added a new suggestion for Crossplatform Video Player, please vote https://xamarin.uservoice.com/forums/258559-xamarin-forms-suggestions/suggestions/11370669-crossplatform-video-audio-player-ios-android-wp

    Sunday, January 10, 2016 2:31 PM
  • User181309 posted

    Event SurfaceCreated (ISurfaceHolder holder) is not raised, why! The Audio play, but without video. Can you help me?

    Thursday, March 10, 2016 1:39 PM
  • User56293 posted

    @RogerSchmidlin Hi Roger, did you manage to get the video to display without filling the whole screen? If so, would you mind sharing how you managed to fix it?

    Monday, April 4, 2016 3:49 PM
  • User52818 posted

    @PaulDiston Yes, I did. But at the moment I play full screen mode in my code. But my implementation allows you to do anything you want. It is a custom video view. I modified the posted code a bit to leave just the relevant code. I took out all my custom control actions. It probably does't compile like this but it should give you a good idea. I hope it helps, good luck :smile:

    This is my custom renderer in the android project

    `

    [assembly: ExportRenderer (typeof(WhatElse.WSVideoView), typeof(WhatElse.Droid.WSVideoViewRenderer))]

    namespace WhatElse.Droid { public class WSVideoViewRenderer : ViewRenderer, MediaPlayer.IOnPreparedListener, TextureView.ISurfaceTextureListener, MediaPlayer.IOnCompletionListener { TextureView _videoview; WSVideoView _ws; string _videoPath; MediaPlayer _mediaPlayer; int _screenHight; int _screenWidth;

        protected override void OnElementChanged (ElementChangedEventArgs<WSVideoView> e)
        {
            base.OnElementChanged (e);
    
            if (e.NewElement == null) {
                return;
            }
            AppContext.MainActivityWindow.AddFlags(WindowManagerFlags.KeepScreenOn);
    
            _ws = e.NewElement;
            _videoPath = _ws.FileSource;
            _videoview = new TextureView (Context);
            _videoview.SurfaceTextureListener = this;
    
            //use a relative layout as a container for the video so that widths / heights are properly respected
            var relLayout = new Android.Widget.RelativeLayout (Context);
            relLayout.SetHorizontalGravity (GravityFlags.CenterHorizontal);
            relLayout.SetVerticalGravity (GravityFlags.CenterVertical);
            relLayout.AddView (_videoview);
            SetNativeControl (relLayout);
        }
    
        public void OnSurfaceTextureAvailable (SurfaceTexture surfaceTexture, int width, int height)
        {
            _screenHight = Resources.DisplayMetrics.HeightPixels;
            _screenWidth = Resources.DisplayMetrics.WidthPixels;
            _mediaPlayer = new MediaPlayer ();
            _mediaPlayer.SetOnPreparedListener (this);
            _mediaPlayer.SetOnCompletionListener (this);
    
            Surface surface = new Surface (surfaceTexture);
            _mediaPlayer.SetSurface (surface);
            Thread myThread = new Thread (StartVideo);
            myThread.Start ();
        }
    
        public bool OnSurfaceTextureDestroyed (SurfaceTexture surface)
        {
            AppContext.MainActivityWindow.ClearFlags(WindowManagerFlags.KeepScreenOn);
            if (_mediaPlayer != null) {
                _mediaPlayer.Stop ();
                _mediaPlayer.Release ();
            }
            return false;
        }
    
        public void OnSurfaceTextureSizeChanged (SurfaceTexture surface, int width, int height)
        {
        }
    
        public void OnSurfaceTextureUpdated (SurfaceTexture surface)
        {
        }
    
        protected override void OnConfigurationChanged (Configuration newConfig)
        {
            base.OnConfigurationChanged (newConfig);
            if (newConfig.Orientation == Android.Content.Res.Orientation.Landscape) {
                Device.BeginInvokeOnMainThread (() => SetVideoSize (Math.Max (_screenWidth, _screenHight), Math.Min (_screenWidth, _screenHight)));
            } else {
                Device.BeginInvokeOnMainThread (() => SetVideoSize (Math.Min (_screenWidth, _screenHight), Math.Max (_screenWidth, _screenHight)));
            }
        }
    
        void StartVideo ()
        {
            Device.BeginInvokeOnMainThread (() => {
                try {
                    _mediaPlayer.SetDataSource (Context, Android.Net.Uri.Parse (_videoPath)); 
                    _mediaPlayer.Prepare ();
                } catch (Exception e) {
                    Console.WriteLine ("Starting Video failed: {0}", e.Message);
                }
            });
        }
    
        public void OnPrepared (MediaPlayer mediaPlayer)
        {
            Device.BeginInvokeOnMainThread (() => {
                SetVideoSize (_screenWidth, _screenHight);
                _ws.HandleFinishedLoadingPlayer ();
            });
        }
    
        public void OnCompletion (MediaPlayer mediaPlayer)
        {
            // the mediaplayer never gets to the duration when it finishes playing. That's why we have to do it by hand 
            // needed for the repeat function
            mediaPlayer.SeekTo (mediaPlayer.Duration);
        }
    
        void SetVideoSize (int currentViewWidth, int currentViewHeight)
        {
            float videoProportion = (float)_mediaPlayer.VideoWidth / (float)_mediaPlayer.VideoHeight;
            float screenProportion = (float)currentViewWidth / (float)currentViewHeight;
    
            LayoutParams layoutParameters = _videoview.LayoutParameters;
            if (videoProportion > screenProportion) {
                layoutParameters.Width = currentViewWidth;
                layoutParameters.Height = (int)((float)currentViewWidth / videoProportion);
            } else {
                layoutParameters.Height = currentViewHeight;
                layoutParameters.Width = (int)(videoProportion * (float)currentViewHeight);
            }
            _videoview.LayoutParameters = layoutParameters;     
        }
    }
    

    }

    `

    And this is my custom view class. Again I removed all my custom control stuff to make it simple.

    `

    namespace WhatElse { public class WSVideoView : View { public Action HandleFinishedLoadingPlayerAction;

        public static readonly BindableProperty FileSourceProperty = 
            BindableProperty.Create<WSVideoView,string> (
                p => p.FileSource, string.Empty);
    
        public string FileSource {
            get { return (string)GetValue (FileSourceProperty); }
            set { SetValue (FileSourceProperty, value); }
        }
    
    
        public void SetLoadingFinishedHandler (Action handler)
        {
            HandleFinishedLoadingPlayerAction = handler;
        }
    
        public void HandleFinishedLoadingPlayer ()
        {
            if (HandleFinishedLoadingPlayerAction != null) {
                HandleFinishedLoadingPlayerAction ();
            }
        }
    }
    

    }

    `

    Monday, April 4, 2016 4:27 PM
  • User185417 posted

    @rmarinho

    Can you please provide detail, i follow your guide but it didn't worked.

    Tuesday, April 12, 2016 2:18 PM
  • User185417 posted

    @rmarinho

    <localControls:VideoView FileSource="video.mp4" Grid.RowSpan="2" x:Name="video"></localControls:VideoView>

    Why FileSource is not accessible in code-behind ??

    Tuesday, April 12, 2016 2:21 PM
  • User151021 posted

    did any one find a workaround for my MediaPlayer is also only playing sond not showing the Video i have tried to switch to only using VideoView with out mixing it MediaPlayer but still no win

    Tuesday, May 10, 2016 9:05 AM
  • User167943 posted

    @ScottNimrod said: I have observed that the emulator shows a black screen even though the audio is playing. When I deploy the app to an actual test device (not an emulator), I can observe the video playing. However, I've noticed the aspect ratio being off on the video. Specifically, I observe the video images being stretched to fit the screen when the screen is showing in portrait mode. This makes viewing the video kind of strange.

    OMG - GIVE ME BACK MY HOUR SPENT FIGURING OUT THE BLACK SCREEN!

    Stupid emulator.. thanks man - seriously.

    Sunday, August 28, 2016 11:10 AM
  • User197632 posted

    how to play videos in xamarin forms

    Friday, September 30, 2016 5:03 AM
  • User102830 posted

    I ended up creating a video player component for Xamarin Forms. You can hook into video events (playing, paused, stopped, completed, etc.) and control player operations all from shared code.

    https://components.xamarin.com/view/video-player

    Tuesday, October 4, 2016 1:09 AM
  • User303929 posted

    Adam, does your player load local files? I need to load videos off a list on an SD card. Also does it load them asynchronously? Can I hide the controls and implement touch to pause and then play?

    Saturday, March 11, 2017 3:01 AM
  • User102830 posted

    Yes you can play local files. It is asynchronous in that the video player handles opening the stream as soon as it is handed a path. To hide controls you just set DisplayControls="False".

    Thursday, March 16, 2017 8:28 PM
  • User223012 posted

    Check out this library for a cross platform media player (video and audio). It supports Xamarin Forms as well.

    https://github.com/martijn00/XamarinMediaManager

    Thursday, March 16, 2017 9:45 PM
  • User73 posted

    Is there a way to play a video non streched on Android?.... Xamarin.Forms and PCL and MVVM due to problems with video are being more slow for development than doing with MonoDroid...

    Tuesday, July 25, 2017 5:33 PM
  • User135846 posted

    @RogerSchmidlin Thank you... seriously. Would you believe the guys posting their "paid" video controls below do NOT work correctly? I owe you a beer (if you IM me ur digits - http://beergivr.com/ will send you one)

    Saturday, September 9, 2017 3:19 AM
  • User102830 posted

    If anyone is interested, the Xamarin.Forms video player component has been relocated to here: https://github.com/adamfisher/Xamarin.Forms.VideoPlayer

    Thursday, December 7, 2017 4:04 AM
  • User366752 posted

    using a Scroll View Renderer where I add the MPMoviePlayerController (code at bottom, file attach not working) version UWP ?

    Tuesday, July 31, 2018 6:29 PM