使用Xamarin Forms播放视频

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Xamarin Forms播放视频相关的知识,希望对你有一定的参考价值。

我们正在使用Xamarin.forms在Xamarin中构建应用程序。在应用程序中我们需要播放视频,因此我们为此编写了一些代码。但是,视频没有播放,在android上应用程序崩溃,同时抛出一般错误。

这是代码:

VideoContainer.cs

using System;
using Xamarin.Forms;
using System.Collections.Generic;

namespace MyApp
{
    public class VideoView : View
    {
        public Action StopAction;
        public VideoView ()
        {
            Console.WriteLine("VideoView loaded");
        }

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

VideoViewRender.cs

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 Xamarin.Forms.Platform.Android;
using Android.Media;
using Android.Content.Res;
using Java.Lang;
using MyApp.Droid;

[assembly: ExportRenderer(typeof(VideoView), typeof(VideoViewRenderer))]
//
namespace MyApp.Droid
{
    public class VideoViewRenderer : ViewRenderer
    {
        VideoView videoview;
        MediaPlayer player;
        MediaController mediaController;
        Handler handler = new Handler();
        public VideoViewRenderer()
        {
            Console.WriteLine("VideoViewRenderer loaded");
        }   

        public void SurfaceChanged(ISurfaceHolder holder, global::Android.Graphics.Format format, int width, int height)
        {

        }

        public void SurfaceDestroyed(ISurfaceHolder holder)
        {

        }

        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 void SurfaceCreated(ISurfaceHolder holder)
        {
            player.SetDisplay(holder);
        }

        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;
        }
        //--------------------------------------------------------------------------------

    }
}

会发生什么是VideoView loaded登录到控制台,但VideoViewRenderer loaded不是。我们从the Xamarin forum获得此代码,但无法成功实现它。我们做错了什么?

答案

我认为你的[assembly:...]错误VideoView

有可能ExportRenderer得到Android.VideoView

你应该得到[assembly: ExportRenderer(typeof(MyApp.VideoView), typeof(MyApp.Droid.VideoView))]

另一答案

查看此示例更容易。

https://github.com/logikonline/xamarin-amccorma

请享用!

编辑:请参阅https://github.com/amccorma/xamarin-amccorma最初完成的此实现

[assembly: ExportRenderer(typeof(MyVideoPlayer), typeof(VideoSamples.Droid.MyVideoPlayerRenderer))]
namespace VideoSamples.Droid
{
    public class MyVideoPlayerRenderer : ViewRenderer<MyVideoPlayer, Android.Widget.RelativeLayout>
    {
        private MediaController _MCController;
        private MyVideoView _MyVideoView;
        private bool _AttachedController;
        private Android.Widget.RelativeLayout _MainLayout;

        public MyVideoPlayerRenderer ()
        {
            this._AttachedController = false;
        }

        protected override void Dispose (bool disposing)
        {
            if (this._MCController != null && this._MyVideoView != null) {
                this._MyVideoView.SetMediaController (null);
            }
            if (this._MCController != null) {
                this._MCController.Dispose ();
                this._MCController = null;
            }

            if (this._MyVideoView != null) {
                this._MyVideoView.StopPlayback ();
                this._MyVideoView.Dispose ();
                this._MyVideoView = null;
            }
            base.Dispose (disposing);
        }

        protected override void OnElementChanged (ElementChangedEventArgs<MyVideoPlayer> e)
        {
            base.OnElementChanged (e);
            if (this.Control == null) { 
                var layoutInflater = (LayoutInflater)Context.GetSystemService(global::Android.Content.Context.LayoutInflaterService);
                this._MainLayout = (Android.Widget.RelativeLayout)layoutInflater.Inflate (VideoSamples.Droid.Resource.Layout.VideoLayout, null);    
                SetNativeControl (this._MainLayout);
            }

            this._MyVideoView = this.Control.FindViewById<MyVideoView>(VideoSamples.Droid.Resource.Id.videoView1);


            // full screen hack?  
            ResizeScreen (true); //this.Element.FullScreen);

            // must set reference to root element
            this._MyVideoView.ParentElement = this.Element;

            // pick controller
            this._MCController = new MediaController (this.Context);
            this._MCController.SetMediaPlayer (this._MyVideoView);

            if (this.Element.AddVideoController) {              
                this._AttachedController = true;
                this._MyVideoView.SetMediaController (this._MCController);
            } else {
                this._AttachedController = false;
            }

            // load file
            this._MyVideoView.LoadFile (this.Element.FileSource);

            if (this.Element.AutoPlay) {
                // play if set to autoplay on load
                this._MyVideoView.Play();
            }
        }

        protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged (sender, e);
            var source = this.Element;
            if (source != null && this._MyVideoView != null) {
                if (e.PropertyName == MyVideoPlayer.SeekProperty.PropertyName) {
                    this._MyVideoView.SeekTo ((int)this.Element.Seek);
                } else if (e.PropertyName == MyVideoPlayer.FileSourceProperty.PropertyName) {

                    // load the play file
                    this._MyVideoView.LoadFile (this.Element.FileSource);
                    this._MyVideoView.Play ();
                } else if (e.PropertyName == MyVideoPlayer.AddVideoControllerProperty.PropertyName) {
                    if (source.AddVideoController && this._AttachedController == false) {
                        this._MyVideoView.SetMediaController (this._MCController);
                    } else {
                        this._MyVideoView.SetMediaController (null);
                    }
                } else if (e.PropertyName == MyVideoPlayer.FullScreenProperty.PropertyName) {
                    ResizeScreen (source.FullScreen);
                } else if (e.PropertyName == "OrientationChanged") {
                    ResizeScreen (source.FullScreen);
                } else if (e.PropertyName == MyVideoPlayer.ActionBarHideProperty.PropertyName) {
                    ResizeScreen (source.FullScreen);
                } else if (e.PropertyName == MyVideoPlayer.PlayerActionProperty.PropertyName) {
                    if (source.PlayerAction == VideoState.PAUSE) {
                        this._MyVideoView.Pause ();
                    } else if (source.PlayerAction == VideoState.PLAY) {
                        this._MyVideoView.Play ();
                    } else if (source.PlayerAction == VideoState.RESTART) {
                        this._MyVideoView.SeekTo (0);
                        this._MyVideoView.Play ();
                    } else if (source.PlayerAction == VideoState.STOP) {
                        this._MyVideoView.StopPlayback ();
                    }
                }
            }
        }

        private void ResizeScreen(bool fullscreen)
        {
            var a = this.Context as Activity;
            if (this.Element.ActionBarHide) {
                a.ActionBar.Hide ();
            } else {
                a.ActionBar.Show ();
            }
            if (fullscreen) {
                var p = this._MyVideoView.LayoutParameters as Android.Widget.RelativeLayout.LayoutParams;
                p.Height = Android.Widget.RelativeLayout.LayoutParams.FillParent;

                // added works ok for rotation
                var view = a.Window.DecorView;
                Rect rect = new Rect ();
                view.GetWindowVisibleDisplayFrame (rect);

                var width = (int)this.Element.ContentWidth;
                var height = (this.Element.ActionBarHide) ? rect.Height() : (int)this.Element.ContentHeight; 
                var holder = this._MyVideoView.Holder;

                p.Height = height;
                p.Width = width;

                holder.SetFixedSize (width, height);
                // end

                p.AlignWithParent = true;
                this._MyVideoView.LayoutParameters = p;

            } else {
                var p = this._MyVideoView.LayoutParameters as Android.Widget.RelativeLayout.LayoutParams;
                if (this.Element.HeightRequest > 0 || this.Element.WidthRequest > 0) {
                    if (this.Element.HeightRequest > 0) {
                        p.Height = (int)this.Element.HeightRequest;
                    }
                    if (this.Element.WidthRequest > 0) {
                        p.Width = (int)this.Element.WidthRequest;
                    }
                    this._MyVideoView.LayoutParameters = p;
                }
                p.AlignWithParent = false;
                this._MyVideoView.LayoutParameters = p;
            }

            InvalidLayout ();
        }

        private void InvalidLayout()
        {
            if (this.Element.Orientation == MyVideoPlayer.ScreenOrientation.LANDSCAPE) {

            }
            Xamarin.Forms.Device.BeginInvokeOnMainThread (() => {

                this._MyVideoView.ForceLayout();
                this._MyVideoView.RequestLayout ();
                this._MyVideoView.Holder.SetSizeFromLayout();
                this._MyVideoView.Invalidate ();

            });
        }
    }
}
以上是关于使用Xamarin Forms播放视频的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin Forms:使用 webView 播放本地视频(测试 Android ATM)

如何使用 xamarin.forms 在移动设备中选择多个音频和/或视频文件?

Xamarin Forms Webview html 视频不在 iOS 设备上播放

Xamarin Forms 中的视频播放器在最小化和恢复时消失了

最新 iOS 更新 (12.2) 后,本地存储中的视频未在 WebView (Xamarin.Forms) 中播放

我应该在 Xamarin.Forms 中使用啥视频或媒体播放器? 3 似乎可用