Access platform-specific APIs within your Xamarin.Forms app
By: Sebastian Jensen
Tags: Mobile App Development, Platform, Xamarin Forms, iOS App Development, Android App Development

Access platform-specific APIs within your Xamarin.Forms app

How you can get access to platform-specific APIs while still keeping a clean architecture by using Dependency Injection Sebastian Jensen Follow Oct 7, 2020 · 5 min read

Introduction

The approach of Xamarin.Forms is that you can write nearly the whole application once and then this app gets compiled to the different mobile operating systems, like Android and iOS. Which means that you most of the time don’t need to write platform-specific code.

But this wasn’t always the case, because at the beginning of Xamarin.Forms development you have to write a lot of platform-specific code if you want to access the sensors of the device to get the current location of the user, for example. For this reason, there were Xamarin Plugins which can be installed in the application to get a wrapper around the platform-specific APIs and the corresponding implementation on each platform. Back in 2018 Microsoft released Xamarin.Essentials a NuGet package which is now part of the Xamarin.Forms templates to provide access to lots of platform-specific APIs, so that you can just access them from your platform independent code.

But this library doesn’t cover everything which means that from time to time you have to access platform-specific APIs. In this blog post I will show you how we can implement a custom service to show toast notifications on Android and iOS and how we can call this service from our platform independent code by using Dependency Injection.

Introducing IToastService

Let’s start by thinking about an interface for our ToastService which we place in the platform independent project of our Xamarin.Forms solution. In this case our service will provide only one method called ShowToast with two parameters. The first parameter contains the message and the second one can change the duration of the displayed time of the toast.

Implementing ToastService on Android and iOS

Now that we have the interface in place, we can start writing the platform-specific implementation by starting with Android. Let’s create a new folder Services in our Android project and create a file called ToastService in this folder. This service will use the Toast class from Android to show the corresponding message on the screen.

For iOS we have to use a different approach, because the concept of a toast isn’t available. We will use the UIAlertController instead and dismiss the alert after a defined period of time, which is in this case fully customizable.

Dependency Injection using DependencyService

Dependency Injection is a technique in which an object receives other objects that it depends on. Xamarin.Forms provides a class called DependencyService which enables Xamarin.Forms apps to use the concept of Dependency Injection to call native platform functionally from the shared code. To use this functionality, you have to mark your platform specific implementations with the Dependency attribute. Then you are able to call the Get method from the DependencyService class to get the corresponding service.

Dependency Injection using Unity Container

For sure it is possible to use the DependencyService from Xamarin.Forms to achieve the goal, but in my opinion, it is not the best architectual idea to use it. You have to mark your services with the Dependency attribute which will cost a little bit of performance, because the app needs to scan for all these attributes and register them properly.

I would prefer to use a different service locator without the dependency to Xamarin.Forms. There a different packages available, but I like to use Unity Container for that, which is a lightweight, extensible dependency injection container. To get Unity Container initialized you have to add two NuGet packages to your platform independent project: Unity.Container and Unity.ServiceLocation.

After the installation we will create a new file called Bootstrapper in our shared code. This class will wire up everything for use, because we will register all our services and all our view models within that class.

You can see that we pass a parameter to the RegisterType method to specify the lifetime of our services or viewmodels. In this case we will use a singleton approach by using ContainerControlledLifetimeManager to have only one instance of the service/view model if we ask the service locator or we are using Dependency Injection to get the instance. There are different LifetimeManagers available, but especially for service I think it is a good approach to work with singletons.

There are two methods in the Bootstrapper available. The method RegisterDependencies registers all platform independent services and view models and sets the ServiceLocator , so that we can access these services and view models via Dependency Injection. The other method is called RegisterPlatformDependency and needs to be called from the platform-specific projects, because here you can add the service like our ToastService to the Unity Container.

Normally you would call the RegisterDependencies method in the file App.xaml.cs before setting the MainPage property. The RegisterPlatformDependency method will be called for Android in the MainActivity class within the OnCreate method.

On the iOS platform we will call the method in the file AppDelegate in the method FinishedLaunching .

Now that we have our service registered in our UnityContainer by using the Bootstrapper we can start creating a view model to use our ToastService by using Dependency Injection.

To be able to manipulate the message in our toast I provide a property ToastMessage which the user can fill with the corresponding message. The view model also provides two commands to show either a short or a long toast. To use Dependency Injection we simply use the constructor and pass in our interface IToastService which we will save in a private field. Now we are able to call the methods of the service which we are doing in the ShowToast method.

We have now everything in place to try a first run of our application. For the UI I’m using an Entry control where the user can enter the message which should be displayed on the toast and two buttons to either show a short or a long toast.

The following animation shows the implementation on Android.

Our Toast implementation on Android

And here you can see the app running on iOS.

Our Toast implementation on iOS

You will find the source code in this GitHub repository.

Conclusion

In this post I showed you how you can easily access the native APIs while using Xamarin.Forms. Just follow these simple steps:

Create an interface in your shared code. Create the platform specific implementations in the platform projects Register your service using the Bootstrapper

By using the Unity Container we have a clean architecture and while using Dependency Injection it easy for us to access the methods in our shared code.