以Xamarin形式播放视频-无法播放视频

时间:2019-07-12 08:41:59

标签: xamarin xamarin.forms

我正在使用Android的视频视图在我的应用中播放视频。当我将来源作为网络链接时,它工作正常,但是当我从本地资源中选择文件时,我在Xamarin Android Player中始终收到“无法播放此视频”消息和黑屏。我遵循了Here中的示例。我已经用Google搜索这个问题,有人说这个问题可能是由于

  • 不受支持的文件格式
  • 不受支持的android版本

我不认为这是我的情况,因为示例项目在同一设备上运行良好。此外,我的项目中还播放了来自URL的视频。我相信我可能缺少解决这个问题的方法。 Xaml:-

  <StackLayout VerticalOptions="FillAndExpand">

    <video:VideoPlayer   AutoPlay="True"  x:Name="xvideoPlayer" WidthRequest="200" HeightRequest="200"  />
    <Button Clicked="Button_Clicked" ></Button>
</StackLayout>

Cs:

 public VideoPlayerPage(string url)
    {

        InitializeComponent();
        BindingContext = videoPlayerPageViewModel = new VideoPlayerPageViewModel();
        NavigationPage.SetHasNavigationBar(this, false);

    }
private async void Button_Clicked(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        btn.IsEnabled = false;
        var FileOperations = DependencyService.Get<IFileOperations>();

        //string pLocalPath = FileOperations.GetFilePath(url, "ErpwebChat");
        string pLocalPath = "content://com.android.externalstorage.documents/document/primary%3ADocument%2FErpwebChat%2F1aecb317-8d56-46c4-b29a-182d2e61093c.mp4";
        //DownloadVideo(url, "videos");



        if (!String.IsNullOrWhiteSpace(pLocalPath))
        {
            xvideoPlayer.Source = new FileVideoSource
            {
                File = pLocalPath
            };
        }
        btn.IsEnabled = true;
    }

VideoPlayerRenderer.droid类:-

  public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, ARelativeLayout>
{
    VideoView videoView;
    MediaController mediaController;    // Used to display transport controls
    bool isPrepared;

    public VideoPlayerRenderer(Context context) : base(context)
    {
    }

    protected override void OnElementChanged(ElementChangedEventArgs<VideoPlayer> args)
    {
        base.OnElementChanged(args);

        if (args.NewElement != null)
        {
            if (Control == null)
            {
                // Save the VideoView for future reference
                videoView = new VideoView(Context);

                // Put the VideoView in a RelativeLayout
                ARelativeLayout relativeLayout = new ARelativeLayout(Context);
                relativeLayout.AddView(videoView);

                // Center the VideoView in the RelativeLayout
                ARelativeLayout.LayoutParams layoutParams =
                    new ARelativeLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent);
                layoutParams.AddRule(LayoutRules.CenterInParent);
                videoView.LayoutParameters = layoutParams;

                // Handle a VideoView event
                videoView.Prepared += OnVideoViewPrepared;

                SetNativeControl(relativeLayout);
            }

            SetAreTransportControlsEnabled();
            SetSource();

            args.NewElement.UpdateStatus += OnUpdateStatus;
            args.NewElement.PlayRequested += OnPlayRequested;
            args.NewElement.PauseRequested += OnPauseRequested;
            args.NewElement.StopRequested += OnStopRequested;
        }

        if (args.OldElement != null)
        {
            args.OldElement.UpdateStatus -= OnUpdateStatus;
            args.OldElement.PlayRequested -= OnPlayRequested;
            args.OldElement.PauseRequested -= OnPauseRequested;
            args.OldElement.StopRequested -= OnStopRequested;
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (Control != null && videoView != null)
        {
            videoView.Prepared -= OnVideoViewPrepared;
        }
        if (Element != null)
        {
            Element.UpdateStatus -= OnUpdateStatus;
        }

        base.Dispose(disposing);
    }

    void OnVideoViewPrepared(object sender, EventArgs args)
    {
        isPrepared = true;
        ((IVideoPlayerController)Element).Duration = TimeSpan.FromMilliseconds(videoView.Duration);
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        base.OnElementPropertyChanged(sender, args);
        if (args.PropertyName == VideoPlayer.AreTransportControlsEnabledProperty.PropertyName)
        {
            SetAreTransportControlsEnabled();
        }
        else if (args.PropertyName == VideoPlayer.SourceProperty.PropertyName)
        {
            SetSource();
        }
        else if (args.PropertyName == VideoPlayer.PositionProperty.PropertyName)
        {
            if (Math.Abs(videoView.CurrentPosition - Element.Position.TotalMilliseconds) > 1000)
            {
                videoView.SeekTo((int)Element.Position.TotalMilliseconds);
            }
        }
    }

    void SetAreTransportControlsEnabled()
    {
        if (Element.AreTransportControlsEnabled)
        {
            mediaController = new MediaController(Context);
            mediaController.SetMediaPlayer(videoView);
            videoView.SetMediaController(mediaController);
        }
        else
        {
            videoView.SetMediaController(null);

            if (mediaController != null)
            {
                mediaController.SetMediaPlayer(null);
                mediaController = null;
            }
        }
    }

    void SetSource()
    {
        isPrepared = false;
        bool hasSetSource = false;

        if (Element.Source is UriVideoSource)
        {
            string uri = (Element.Source as UriVideoSource).Uri;

            if (!String.IsNullOrWhiteSpace(uri))
            {
                videoView.SetVideoURI(Android.Net.Uri.Parse(uri));
                hasSetSource = true;
            }
        }
        else if (Element.Source is FileVideoSource)
        {
            string filename = (Element.Source as FileVideoSource).File;

            if (!String.IsNullOrWhiteSpace(filename))
            {
                videoView.SetVideoPath(filename);
                hasSetSource = true;
            }
        }
        else if (Element.Source is ResourceVideoSource)
        {
            string package = Context.PackageName;
            string path = (Element.Source as ResourceVideoSource).Path;

            if (!String.IsNullOrWhiteSpace(path))
            {
                string filename = Path.GetFileNameWithoutExtension(path).ToLowerInvariant();
                string uri = "android.resource://" + package + "/raw/" + filename;
                videoView.SetVideoURI(Android.Net.Uri.Parse(uri));
                hasSetSource = true;
            }
        }

        if (hasSetSource && Element.AutoPlay)
        {
            videoView.Start();
        }
    }

    // Event handler to update status
    void OnUpdateStatus(object sender, EventArgs args)
    {
        VideoStatus status = VideoStatus.NotReady;

        if (isPrepared)
        {
            status = videoView.IsPlaying ? VideoStatus.Playing : VideoStatus.Paused;
        }

        ((IVideoPlayerController)Element).Status = status;

        // Set Position property
        TimeSpan timeSpan = TimeSpan.FromMilliseconds(videoView.CurrentPosition);
        ((IElementController)Element).SetValueFromRenderer(VideoPlayer.PositionProperty, timeSpan);
    }

    // Event handlers to implement methods
    void OnPlayRequested(object sender, EventArgs args)
    {
        videoView.Start();
    }

    void OnPauseRequested(object sender, EventArgs args)
    {
        videoView.Pause();
    }

    void OnStopRequested(object sender, EventArgs args)
    {
        videoView.StopPlayback();
    }
}

我正在使用.mp4格式 其余所有类均与示例应用程序Here中的类相同 任何帮助将不胜感激 。 !

编辑-设备日志(从按钮单击无法播放错误) Here

2 个答案:

答案 0 :(得分:0)

我在ios渲染器中遇到了同样的问题,因此我解决该问题的方法是将SetSource函数中的条件更改为

else if (Element.Source is FileVideoSource)
    {
        string uri = (Element.Source as FileVideoSource).File;

        if (!String.IsNullOrWhiteSpace(uri))
        {
            var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var path = Path.Combine(documents, uri);

            NSUrl url = NSUrl.CreateFileUrl(path, null);
            asset = AVAsset.FromUrl(url);
        }
    }

由于某种原因,无法将整个路径作为字符串传递,因此您可以传递文件名并在customrenderer中编写创建路径的逻辑 这是我的问题的链接 Xamarin video player unable to play video from simulator document folder

答案 1 :(得分:0)

尝试将视频播放器从StackLayout中取出,我一直在运行Xamarins自己的视频播放器示例,复制了系统文件和类结构,但只有黑屏。 把它拿出来堆和宾果游戏