OS native functions in Xamarin.Forms

Xamarin.Forms already offers a certain set of cross-platform implemented functions. These are already included in the framework and can be used “out of box”. However, there are certain functionalities which are not accessible without custom programming.

The Xamarin framework offers a wonderful functionallity here to “pick up” such self-written methods from the right platform. The keyword is DependencyService.

Example

Let’s take the classic example of file access. iOS and Android process access to files individually, so here we have to implement a platform-specific variant in each case, and then make it externally accessible.

create the interface

First of all, we create an interface with the methods we want to use later. The interface can be created at any location in the cross-platform code:

public interface IFileHelper
{
  string GetLocalFilePath(string fileName);
  string GetExternalFilePath(string path);
}

It’s quite trivial. Anything you want can come in here.

implement the interface in platform project

Now we implement the functionallity in our desired target platform. I take Android as an example here, since I haven’t programmed the iOS side yet:

[assembly: Dependency(typeof(FileHelper))]
namespace PSM.Droid
{
  public class FileHelper : IFileHelper
  {
    public string GetLocalFilePath(string filename)
    {
      string path = System.Environment
                      .GetFolderPath(System
                        .Environment
                        .SpecialFolder
                        .Personal
                      );
      return Path.Combine(path, filename);
    }

    public string GetExternalFilePath(string path)
    {
      string extPath = Android.OS
                              .Environment
                              .ExternalStorageDirectory
                              .AbsolutePath;
      return Path.Combine(extPath, path);
    }
  }
}

So we create a new class in our Android project and write an annotation above the namespace [assembly: Dependency(typeof(FileHelper))]. This will let Xamarin know that our class is available for a possible dependency injection. (typeof(FileHelper) is in this case the class itself in which we are currently located).

Now we implement the interface into our class (remember it was called IFileHelper), and we are done. Of course, the methods have to be programmed out, depending on what we want to do (in our example we want to return the path of the external memory).

use the methods in cross platform code

If we want to access this now, we have to register our interface first of all. A very good place is when starting the app, for example in the App.xaml.cs:

DependencyService.Register<IFileHelper>();

We can call our interface everywhere from our code now:

string path = DependencyService.Get<IFileHelper>()
              .GetExternalFilePath("/my/custom/path");

Using the DependencyService module, Xamarin now selects the implementation depending on the current platform and returns an instance of the corresponding class. On this class we can now call our function.

Done!

troubleshooting

I solved the problem that the Get() function of the DependencyService sometimes returns null. It was not possible to see in which case this occurred. Usually Xamarin manages to find the implementation by itself. Should this also happen to you, it is a good idea to register the implementation directly.
The register()method offers an overload here, with which you pass the interface as the first type and the implementation as the second type. So Xamarin knows directly what it has to take.

DependencyService.Register<IFileHelper, FileHelper>();

Of course this has to be done in the platform specific project, so in case of Android in the MainActivity.