Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Android Video Player using Xamarin.Forms

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 ();
    }
}
«1

Posts

  • KanwarBadyalKanwarBadyal AUMember
    edited September 2014

    @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?

  • rmarinhormarinho PTMember, Insider, Beta Xamurai

    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 ?

  • It works perfectly!

  • KeithRoweKeithRowe USMember

    @rmarinho‌ - Awesome, worked perfectly, thanks!

  • KanwarBadyalKanwarBadyal AUMember
    edited September 2014

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

  • rmarinhormarinho PTMember, Insider, Beta Xamurai

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

  • @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.

  • JefimijanaJefimijana USMember ✭✭

    @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

  • KanwarBadyalKanwarBadyal AUMember

    @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"))

  • JefimijanaJefimijana USMember ✭✭

    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<CustomRenderedViews.VimeoView, VideoView>, 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

  • AliAkramAliAkram USMember

    @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))]

  • AliAkramAliAkram USMember

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

  • TedebusTedebus USMember ✭✭

    @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

  • AliAkramAliAkram USMember

    @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

  • LannyDeVaneyLannyDeVaney USMember ✭✭

    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.

  • TedebusTedebus USMember ✭✭
    edited January 2015

    @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

  • AliAkramAliAkram USMember
    edited January 2015

    @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?

  • Nando779Nando779 USMember

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

  • TedebusTedebus USMember ✭✭

    @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...

  • 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 ?

  • TedebusTedebus USMember ✭✭
    edited February 2015

    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.

  • aniltananiltan USMember

    @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!

  • hardik.4160hardik.4160 USMember

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

  • NithyaNithya USUniversity ✭✭

    @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

  • NithyaNithya USUniversity ✭✭

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

  • JitendraPatelJitendraPatel INMember
    edited May 2015

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

  • Aniket_SonsaleAniket_Sonsale USMember ✭✭

    how to add play/pause/stop buttons ?

  • JitendraPatelJitendraPatel INMember

    @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

  • Aniket_SonsaleAniket_Sonsale USMember ✭✭

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

  • PatrickFrankPatrickFrank USMember ✭✭

    @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?

  • purnimapurnima USMember ✭✭

    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

  • purnimapurnima USMember ✭✭

    @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.

  • ScottNimrodScottNimrod USMember ✭✭

    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.

  • AndyShokalookAndyShokalook USUniversity ✭✭

    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<YOURAPPNAME.VideoView, VideoView>, 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);
        }
    }
    

    }

  • Ruchi.1451Ruchi.1451 USMember ✭✭

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

  • gbirbilisgbirbilis GRMember

    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.

  • RogerSchmidlinRogerSchmidlin CHUniversity ✭✭✭

    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?

  • RogerSchmidlinRogerSchmidlin CHUniversity ✭✭✭

    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.

  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    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.

Sign In or Register to comment.