On The Dot...
Talking about all things .NET related

Xamarin Android Video Playback - Part 4: Handling Network Connectivity

Wednesday, August 5, 2015 11:24 PM

This is the last post in my 4 part series. The previous posts in this series covered the basics for creating a simple Xamarin.Android Video Player application. Feel free to check them out to see how we built a basic Video Player:

Part 1 – Using VideoView

Part 2 – Adding Media Controls

Part 3 – Progress Indicator and Orientation Changes

In this final post, we will polish off our Video Player by taking steps to ensure the application does not fail in the event a network connection isn’t present, since we are loading videos from an external site. We will listen for changes in the network connection while the application is running so that when the connectivity state changes we can handle it accordingly. We will display a relevant error message when no connection is found, and we will attempt to resume the video playback when the connection is restored.

Let’s take a look at the classes provided through the API which enables us to monitor the current network connection on a device.

ConnectivityManager and BroadcastReceiver

The ConnectivityManager is a class which provides information on the current network connection (i.e. whether there is a connection and the type of connection), monitors for network connectivity changes, and broadcasts a connectivity action when any connection details have changed. 

The BroadcastReceiver is a base class that will receive notifications in the form of intents when another application or the system triggers the SendBroadcast(Intent) method. An intent will contain an action string and optional data that will be received by any applications that are registered as receivers.

To enable your application to listen for connectivity change notifications broadcast by the ConnectivityManager, you must register a broadcast receiver by adding the following line to your AndroidManifest.xml file:

image

In addition to that, because you are accessing information about network state, you will need to include the necessary permission in your AndroidManifest as well:

image

Next, you must extend the BroadcastReceiver base class and override its OnReceive(Context, Intent) method. Within this override method, you can check the intent’s Action to determine if and how you will respond to the broadcast intent within your own application.

The Connectivity Plugin

Now that you have an understanding of the basic components that help you to monitor network connections in an Android application, I have some good news – Xamarin’s own James Montemagno has already written a plugin for that and made it available as a Nuget package :)

The Connectivity Plugin contains the necessary code for retrieving information about the network, monitoring for network connections and listening for connection changes.

The best part of this plugin is that it is a complete cross platform solution, so that you can use it in your client applications and Portable Class Libraries. He has provided both the abstraction layer and the necessary platform-specific implementations (ie. Android, iOS, Windows 8.1 and Windows Phone (8.0 & 8.1)). The Connectivity Plugin handles loading the platform-specific implementation logic. All you have to do is make the appropriate calls through the plugin’s IConnectivity interface which is exposed through the CrossConnectivity.Current static property. At runtime, the Connectivity Plugin will load the platform-specific implementation and make it available through CrossConnectivity.Current.

This may not seem like a big deal now, since we are only targeting Android. But if you ever wanted to expand your application to target multiple platforms, you will realize a huge time savings from only having to call one API rather than code each platform’s implementation to achieve the desired result.

James has made the entire solution for the Connectivity Plugin available on his Github account. Feel free to peruse the code or download it and customize it for your needs.

Side Note: When using 3rd party components, be sure to provide proper attribution within your application - for example, by adding a Credits page that lists the components you used, along with their respective authors. These components are provided by developers to make your life easier, so it’s important to give credit where credit is due.

Using the Connectivity Plugin in our Android Project

To add the Connectivity Plugin to our application, right-click on the project in Solution Explorer, and select Manage Nuget Packages. Within the Manage Nuget Packages dialog, search for Xamarin Connectivity. Install the Connectivity Plugin for Xamarin and Windows.

Once the Connectivity Plugin has been added to the project, take a look at the project’s references. Notice that it added two new references to the project – Connectivity.Plugin and Connectivity.Plugin.Abstractions.

clip_image0041

In the MainActivity code file, add using directives for these namespaces:

image

There are two things we care about and need to account for:

1) listening for changes in network connectivity

2) performing the appropriate check so the video attempts to load only when a network connection is present

To monitor for changes in network connectivity, we need to register an event handler for the ConnectivityChanged event. Add the following to the OnStart method:

CrossConnectivity.Current.ConnectivityChanged += OnCurrentConnectivityChanged;

Be sure to unregister the event handler in the OnStop method as well.

Next, we need to include the action we want taken when the network connectivity changes. In this scenario, we only care about whether or not the video can play. Since the LaunchVideo method is responsible for starting the video playback, let’s include a check to only start the playback if the network is currently connected, so that no matter where it’s called from, we are performing our due diligence. I am also going to ensure that the video player isn’t in the middle of playing the video already since LaunchVideo is called from multiple locations.

image

Then in our OnCurrentConnectivityChanged event, we can simply call the LaunchVideo method as is, since it’s already checking to ensure an active connection before playing the video. Alternatively, you could check the state of the connection within this event handler through the ConnectivityChangedEventArgs.IsConnected property. It’s up to you, whichever way you prefer to handle it.

Now, we want to be able to display a status message when the network connection is lost. Let’s add a TextView to the MainActivity layout.

image

Notice that the text of the control is set to a custom string definition. Add the following to your Strings.xml file:

image

With the TextView in place, we now need to ensure we set the view states on the VideoView, the ProgressBar and our new TextView based on connection state. When there is no network connection, we want only the status message (ie. the TextView) to display, otherwise it is hidden and the ProgressBar and VideoView will display.

Let’s create a separate method called UpdateVideoPlayerState, and include the code to achieve this:

image

However, we also need to account for hiding the TextView, and displaying the VideoView and the ProgressBar when the network is connected. We also want to be able to call this method anytime we need to update the state of the controls in the video player, so let’s extend it to also be able to hide the ProgressBar in the event the video is ready to play. We can do this by passing in a boolean parameter to indicate the state the video player is in when connected, as follows:

image

Again, note that we are also checking to make sure the video player isn’t in the midst of playing the video, since this method is also called from multiple locations.


Tip: If you’re wondering why we do not set the VideoView’s Visibility to Gone or Invisible when the ProgressBar is displayed, it is because the VideoView will not fire events when hidden. Since we registered an event handler for its Prepared event in order to determine when to trigger the video playback, we need to ensure it remains Visible in this scenario.


 

Now we can simply add the call to UpdateVideoPlayerState, passing in a false value when the video player activity first starts, when the configuration changes or connectivity changes.

When the OnVideoPlayerPrepared event is triggered, we know the video is ready to play, so let’s call updateVideoPlayerState passing in a true value, as follows:

image

Last but not least, don’t forget to modify the AndroidManifest.xml to register a broadcast receiver and to request permission to access network state as we discussed earlier.

Playing Video only when connected to WiFi

If you only want the application to play the video when connected to a WiFi network, you can easily modify the existing code to check to see if the device is currently connected to WiFi. The Connectivity Plugin exposes a collection of all the current active connection types. So we can include a bool property which returns true or false if the device has a WiFi connection:

image

Note that we are using a simple LINQ query to check for a WiFi connection type. This requires the inclusion of the following using directive within your class:

image

Replace the checks from CrossConnectivity.Current.IsConnected to IsConnectedToWiFi.

At this point, you can run and test the application. Play around with turning on/off WiFi connections while the video is loading and while the video is playing to see what happens. I know you will find more ways to improve upon this sample application just by testing it out. I hope this gives you a good starting point to work from. You can check out the completed project on my Github account.




Feedback

# re: Xamarin Android Video Playback - Part 4: Handling Network Connectivity

Thank you 4/17/2017 5:29 PM | Hamed

# re: Xamarin Android Video Playback - Part 4: Handling Network Connectivity

Thanks, excellent tutorial. 7/11/2017 3:28 PM | Georges

Post a comment