【问题标题】:Play video with Xamarin Forms使用 Xamarin Forms 播放视频
【发布时间】:2016-02-04 20:22:21
【问题描述】:

我们正在使用 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 获得了这段代码,但未能成功实现。我们做错了什么?

【问题讨论】:

    标签: c# android xamarin xamarin.ios xamarin.forms


    【解决方案1】:

    我认为你的[assembly:...] 弄错了VideoView。

    有可能ExportRenderer得到Android.VideoView。

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

    【讨论】:

      【解决方案2】:

      查看此示例更容易。

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

      【讨论】:

      • 请注意,将链接发布到您自己的 github 项目但没有附带代码来解释如何使用它可能会被某些人视为self-promotion。
      • 对不起 - 我前一段时间把它分叉了,并不想申请功劳。
      猜你喜欢
      • 2019-08-28
      • 1970-01-01
      • 2018-06-03
      • 2017-12-30
      • 2020-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多