I'm using Android's Video View to play a video in my app. It works fine when I put source as a web-link but I keep getting a "Can't play this video" message and a black screen in the Xamarin Android Player when I choose file from Local Resource. I have followed sample from Here. I have googled the issue some say the issue is may be because of
- Unsupported file format
- Unsupported android version
I Don't think this could be in my case as the sample project is running fine on same device .Moreover in my project video from URL are also played. I believe I might be missing a piece to fix this. 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 class:-
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();
}
}
I am using .mp4 format Rest all classes are same as in the sample app Here Any help will be appreciated . !
Edit - Device log(From Button Click to Cant play Error) Here
...Unable to open content...
The error is in your log, do you have permission (manifest and runtime permission to external storage) and how are you determining your :content://" path (you can not just make that up, it needs to be retrieved from the media manager). – SushiHangover