Video Playback in Your Xamarin.Android Apps – Part 2: Adding Media Controls

Originally posted on: http://geekswithblogs.net/lorilalonde/archive/2015/07/22/video-playback-in-your-xamarin.android-apps—part-2-adding.aspx

In Part 1 of this series, we developed a simple video player using Android’s VideoView. However, in testing the application, it is obvious that there are some key features missing. Let’s take a look at how we can improve our Video Player application to provide a better user experience.

Where are the media controls?

The first noticeable thing that seems to be missing from our Video Player is the play, rewind, and fast forward buttons, as well as the progress slider that we are used to seeing when watching videos in other popular video players. The user will not be able to control video playback without it, which isn’t ideal. Luckily for us, it is very easy to incorporate this within our Xamarin.Android application.

The Android API provides a MediaController view, which contains the play/pause, skip forward, and skip back buttons along with a progress slider. To make use of the MediaController, we will need to instantiate it programmatically, and associate it with the VideoView, as follows:

private MediaController mediaController;

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.Main);

    videoPlayer = FindViewById<VideoView>(Resource.Id.PlayerVideoView);
    mediaController = new MediaController(this, true);
    videoPlayer.SetMediaController(mediaController);
}

The constructor we are using for the MediaController requires that we pass in the current context, which is the current Activity, and a boolean value to indicate whether or not to show the rewind and fast forward buttons. With the code above in place, the MediaController will display the Play/Pause button, the rewind and fast forward buttons, and the progress slider. If you wish to hide the fast forward and rewind buttons, simply pass in false as the second parameter value instead.

To ensure that any action the user takes on the MediaController affects the video playback accordingly, we must associate the MediaController with the VideoView by calling the VideoView’s SetMediaController method and passing in a reference to the MediaController. Not only does this allow the user to control the video playback with the controller, but it also registers a touch listener that is associated with the VideoView so that when the view is tapped, the MediaController will appear. There is nothing else we need to do at this point. We can run the application and the MediaController will just work. We can play, pause, fast forward and rewind the video without any additional coding needed on our end. When the MediaController disappears from the view, tap the video to make it reappear.

Tip: In the event that you are creating an application which allows users to manage a playlist of videos, and you want to allow them to skip to the navigate through the video queue, you will need to register event handlers for the MediaController’s PreviousClick and NextClick events. Within those events, include your custom code to load the next or previous video in the queue. Once you have registered for those events, you will notice the Previous and Next buttons will appear in the MediaController.

Test out the application so far, play with the media controls and switch the device orientation from portrait to landscape mode while the video is playing. Notice that when the video playback starts, we don’t see the MediaController on the screen at all. In order to display the controls, the user must touch the video to force it appear. This isn’t really intuitive. It would be ideal to show the user that the MediaController is there when the video starts to play, and then hide it after a brief period, let’s say 3 seconds.

The MediaController provides a Show method, which accepts a timeout in milliseconds for this purpose. It will force the MediaController to appear and remain visible for the specified time.

Since we want the controller to appear when the video playback starts, we will handle this in the VideoView’s Prepared event, which is triggered when the video is ready to play. Register this event in the Activity’s OnStart method:

protected override void OnStart()
{
    base.OnStart();

    videoPlayer.Prepared += OnVideoPlayerPrepared;

    LaunchVideo();
}

In the same respect, we should unregister the event in the OnStop method:

protected override void OnStop()
{
    base.OnStop();
    videoPlayer.Prepared -= OnVideoPlayerPrepared;
}

Next, we will add our custom OnVideoPlayerPrepared event handler and call the MediaController’s Show method, as follows:

private void OnVideoPlayerPrepared(object sender, EventArgs e)
{
    //show media controls for 3 seconds when video starts to play
    mediaController.Show(3000);
}

Screenshot_2015-07-22-13-30-53

Run the application in portrait mode. Notice that the media controls are displayed at the bottom of the screen, far removed from the video.

Would it be preferable to render the controller as an overlay on the video? We can easily make that change by calling the MediaController’s SetAnchorView method and passing in a reference to the VideoView. This will enable the MediaController to know where to position itself when it is rendered onscreen. The media controls will then be displayed as an overlay at the bottom of the anchored view.

 

To achieve this effect, add a call to the SetAnchorView method in the OnVideoPlayerPrepared event:

private void OnVideoPlayerPrepared(object sender, EventArgs e)
{
    mediaController.SetAnchorView(videoPlayer);

    //show media controls for 3 seconds when video starts to play
    mediaController.Show(MediaControllerTimeout);
}

Tip: If you attempt to call SetAnchorView from the OnCreate or OnStart methods, it will still render at the bottom of the screen. This is because the height of the VideoView is not known at this time. It’s best to call this method within the VideoView’s Prepared event when the video is loaded and its size is known, to ensure the controller is properly anchored to the VideoView.

Screenshot_2015-07-22-13-32-20

Run the application again ensuring the device is upright (in portrait mode).

Notice that the MediaController appears as an overlay on the VideoView, aligned with the bottom of video. This is much nicer than having the controller floating at the bottom of the screen away from the video itself.

Wrapping Up

In this post, we built upon our basic Video Player application by associating a MediaController to the VideoView, enabling users to control video playback (i.e. pause, resume, skip forward and rewind). We also covered how to anchor the controller to the VideoView and force the controller to appear for a few seconds when the video first loads. In Part 3 of this series, we will look at providing some polish to the VideoPlayer by handling video playback when the orientation changes, and displaying a progress indicator while the video is loading.


Source: GeekswithBlogs – Lori Lalonde