Show / Hide Table of Contents

    Using the DependencyService with DEM

    Xamarin.Forms includes a DependencyService to let shared code to easily resolve Interfaces to platform-specific implementations, allowing you to access features of the iOS and Android from your PCL or Shared Project.

    The problem with Xamarin's DependencyService is that it requires a static call to DependencyService.Get<> in your shared code to get a platform-specific instance of the interface at run time. This makes your Services or other elements less testable, and hides the dependencies of your class.

    DEM allowing you to simply request any dependencies that have been registered with AutoFac via your class constructor.

    Step 1: Add an interface to the shared project

    Add an interface to the shared project that will define the contract for our service:

        public interface IUniqueDeviceIdentifierFactory : IApplicationService
        {
            string GetId();
        }
    

    Step 2: Implement our interface

    Add a class that implements our interface to each specific platform

    iOS

        public class OSUniqueDeviceIdentifierFactory : IUniqueDeviceIdentifierFactory
        {
            string id = null;
    
            public string GetId()
            {
                return id ?? (id = GetSerialNumber());
            }
    
            [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
            static extern uint IOServiceGetMatchingService(uint masterPort, IntPtr matching);
    
            [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
            static extern IntPtr IOServiceMatching(string s);
    
            [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
            static extern IntPtr IORegistryEntryCreateCFProperty(uint entry, IntPtr key, IntPtr allocator, uint options);
    
            [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
            static extern int IOObjectRelease(uint o);
    
            string GetSerialNumber()
            {
                var serial = string.Empty;
    
                try
                {
                    var platformExpert = IOServiceGetMatchingService(0, IOServiceMatching("IOPlatformExpertDevice"));
    
                    if (platformExpert != 0)
                    {
                        var key = (NSString)"IOPlatformSerialNumber";
    
                        var serialNumber = IORegistryEntryCreateCFProperty(platformExpert, key.Handle, IntPtr.Zero, 0);
    
                        if (serialNumber != IntPtr.Zero)
                        {
                            serial = Runtime.GetNSObject<NSString>(serialNumber);
                        }
    
                        IOObjectRelease(platformExpert);
                    }
                }
                catch (Exception)
                {
                }
    
                return serial;
            }
        }
    

    Andoroid

        public class DroidUniqueDeviceIdentifierFactory : IUniqueDeviceIdentifierFactory
        {
            static JniPeerMembers buildMembers = new XAPeerMembers("android/os/Build", typeof(Build));
    
            static string GetSerialField()
            {
                try
                {
                    const string id = "SERIAL.Ljava/lang/String;";
    
                    var value = buildMembers.StaticFields.GetObjectValue(id);
    
                    return JNIEnv.GetString(value.Handle, JniHandleOwnership.TransferLocalRef);
                }
                catch
                {
                    return string.Empty;
                }
            }
    
            string id = string.Empty;
    
            public string GetId()
            {
                if (!string.IsNullOrWhiteSpace(id))
                {
                    return id;
                }
    
    
                id = GetSerialField();
    
                if (string.IsNullOrWhiteSpace(id) || id == Build.Unknown || id == "0")
                {
                    try
                    {
                        var context = CrossCurrentActivity.Current.Activity ?? Application.Context;
    
                        id = Secure.GetString(context.ContentResolver, Secure.AndroidId);
                    }
                    catch (Exception ex)
                    {
                        //Android.Util.Log.Warn("DeviceInfo", "Unable to get id: " + ex.ToString());
                    }
                }
    
                return id;
            }
        }
    

    Step 3: Register with IPlatformInitializer

    iOS

        public class OsIntializer : IPlatformInitializer
        {
            public virtual void RegisterTypes(ITypeCatalog typeCatalog)
            {
                typeCatalog.Add(new AppServiceInfo<DroidUniqueDeviceIdentifierFactory, IUniqueDeviceIdentifierFactory>());
            }
        }
    

    Andoroid

        public class DroidIntializer : IPlatformInitializer
        {
            public void RegisterTypes(ITypeCatalog typeCatalog)
            {
               typeCatalog.Add(new AppServiceInfo<OSUniqueDeviceIdentifierFactory, IUniqueDeviceIdentifierFactory>());
            }
        }
    

    Step 4: Use the Service

              public DeviceData(IConfiguration configuration, IUniqueDeviceIdentifierFactory uniqueDeviceIdentifierFactory, 
                ITokenIdentifierFactory tokenIdentifierFactory)
            {
                this.configuration = configuration;
                this.uniqueDeviceIdentifierFactory = uniqueDeviceIdentifierFactory;
            }
    

    As you can see, you no longer need to make a call to the static Xamarin.Forms.DependencyService. Just ask for it in your Service or ViewModel constructor, and DEM will use the container to resolve the instance and provide it to you.

    You can also gain access to Xamarin's DependencyService by using the IDevice interface. This interface removes the static call in your code, but still gives you access to Xamarin's DependencyService API.

        public MainPageViewModel(IDeviceService deviceService)
        {
            var deviceId = deviceService.GetService<IUniqueDeviceIdentifierFactory>().GetId();
        }
    
    Back to top Copyright 2020 Asseco SEE