Accessing native platform features straight from your Xamarin Forms code

Using Xamarin Forms is a great way to create real cross platform native apps with maximum code re-use.  In fact, it’s possible to create the UI and business logic for an entire app for iOS, Android and Windows without ever leaving a PCL.

Sooner or later though, you are going to find yourself needing to dive down into the individual platforms. This could be to access device features, such as the GPS or camera, or maybe some platform specific styling that Xamarin Forms has yet to expose.

For me, Dependency Services are the real power behind Xamarin Forms. You have the sheer productivity of the Forms abstraction coupled with the full control of the platform when you need it.

Creating a Dependency Service

In this example we’ll create a dependency service that calls down to the platform to find the devices IP address.  We’ll need to do three things:

  • Create an interface to implement,
  • Write the platform specific code and…
  • Locate that code and call it.

The Interface

The first thing we need is an interface. This lives in our shared code and defines the call that we will make to the platform specific implementation.

In our PCL (the example app PCL is “Dependency.Core”) we’ll create IIpAddressManager, with one method GetIpAddress().

namespace DependencyApp.Core.Interfaces
{
   public interface IIpAddressManager
   {
      string GetIpAddress();
   }
}

Platform specific implementations

Next we create the implementations on the platforms. These classes require a parameterless constructor and, along with the platform code, need to be marked with an attribute to register the class.  This attribute enables the framework to find your implementations and call the methods.

Let’s start with Android, like to keep all the dependency classes together in the folder “Dependecies”:

using System.Net;
using DependencyApp.Core.Interfaces;
using Xamarin.Forms;

[assembly: Dependency(typeof(DependencyApp.Droid.Dependencies.IpAddressManager))]
namespace DependencyApp.Droid.Dependencies
{
    internal class IpAddressManager : IIpAddressManager
    {
        public string GetIpAddress()
        {
            var addresses = Dns.GetHostAddresses(Dns.GetHostName());

            return addresses?[0]?.ToString();
        }
    }
}

…followed by the iOS implementation:

using System.Net.NetworkInformation;
using System.Net.Sockets;
using DependencyApp.Core.Interfaces;
using Xamarin.Forms;

[assembly: Dependency(typeof(DependencyApp.iOS.Dependencies.IpAddressManager))]
namespace DependencyApp.iOS.Dependencies
{
    internal class IpAddressManager : IIpAddressManager
    {
        public string GetIpAddress()
        {
            var ipAddress = "";

            foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces())
            {
                if (netInterface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 ||
                    netInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
                {
                    foreach (var addrInfo in netInterface.GetIPProperties().UnicastAddresses)
                    {
                        if (addrInfo.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            ipAddress = addrInfo.Address.ToString();

                        }
                    }
                }
            }

            return ipAddress;
        }
    }
}

Calling the code

Now we have the implementations in place, we can head back to our PCL and use the DependencyService locator to call the code.

var ipAddress = DependencyService.Get<IIpAddressManager>().GetIpAddress();

Easy as that.

Wrap-up

As you get started with Xamarin Forms, you’ll find that Dependency Services will become a staple of your app development, unlocking heaps of functionality for your apps.

You can download the example code at the XamarinInsider repo.