Corrado's Blog 2.0

Online thoughts of a technology funatic

Get device unique identifier in Xamarin Forms

Last week I introduced some ISV to the wonderful world of Xamarin and while discussing Xamarin Forms a few of them asked how to get an identifier that uniquely identifies a device.

I had the same issue in the past with a Windows Phone application so I know how retrieve it on this platform and I remember speaking with the guy that was working on the same app for iOS that he told me that Apple changed the policy so the API that was used in the past was no longer available and he had to find a workaround, more on this later.

The answer to the original question is quite easy from the architectural side: Just use a Dependency Service and you’re done, here are the steps:

Let’s create a IDevice interface in the common/shared project and let’s add a GetIdentifier method

public interface IDevice
 {
  string GetIdentifier();  
 }

Once done you can easily get device unique identifier within shared code using this snippet:

IDevice device = DependencyService.Get<IDevice>();
string deviceIdentifier = device.GetIdentifier();

Let’s now implement device specific code, starting from Windows Phone, add this class to Windows Phone project and add ID_CAP_IDENTITY_DEVICE capability.

[assembly: Xamarin.Forms.Dependency(typeof(WinPhoneDevice))]
namespace XFUniqueIdentifier.WinPhone
{
 public class WinPhoneDevice : IDevice
 {
  public string GetIdentifier()
  {
   byte[] myDeviceId = (byte[])Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("DeviceUniqueId");
   return Convert.ToBase64String(myDeviceId);
  }
 }
}

Now add following class to Android project:

[assembly: Xamarin.Forms.Dependency(typeof(AndroidDevice))]
namespace XFUniqueIdentifier.Droid
{
 public class AndroidDevice : IDevice
 {
  public string GetIdentifier()
  {
   return Settings.Secure.GetString(Forms.Context.ContentResolver, Settings.Secure.AndroidId);
  }
 }
}

And now the hardest part: iOS developer used to get device identifier using Device UniqueIdentifier api but this has deprecated by Apple so an alternative has to be found.

After some investigations (also considered generating unique id at startup but this would fail if app is reinstalled) I found this post on Xamarin forums so kudos goes to the original author.

It’s now time to add a new class to iOS project with following code:

[assembly: Xamarin.Forms.Dependency(typeof(IOSDevice))]
namespace XFUniqueIdentifier.iOS
{
 using System.IO;
 using System.Runtime.InteropServices;

 public class IOSDevice : IDevice
 {
  [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
  private static extern uint IOServiceGetMatchingService(uint masterPort, IntPtr matching);

  [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
  private static extern IntPtr IOServiceMatching(string s);

  [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
  private static extern IntPtr IORegistryEntryCreateCFProperty(uint entry, IntPtr key, IntPtr allocator, uint options);

  [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
  private static extern int IOObjectRelease(uint o);

  public string GetIdentifier()
  {
   string serial = string.Empty;
   uint platformExpert = IOServiceGetMatchingService(0, IOServiceMatching("IOPlatformExpertDevice"));
   if (platformExpert != 0)
   {
    NSString key = (NSString) "IOPlatformSerialNumber";
    IntPtr serialNumber = IORegistryEntryCreateCFProperty(platformExpert, key.Handle, IntPtr.Zero, 0);
    if (serialNumber != IntPtr.Zero)
    {
     serial = NSString.FromHandle(serialNumber);
    }

    IOObjectRelease(platformExpert);
   }

   return serial;
  }  
}

And you’re done, have fun and make a good use of device unique id. Smile

8 Responses to “Get device unique identifier in Xamarin Forms”

  1. [...] Get device unique identifier in Xamarin Forms « Corrado’s Blog 2.0 How to get a unique device id in xamarin forms [...]

    Pingback by Xamarin Link Roundup – 9 Feb 2015 — Kym Phillpotts — 09/02/2015 @ 02:57

  2. Hi !

    As it says in the post, IOKit is forbidden by Apple. The iOS app will be rejected if we use it.

    Do you have any other solutions ?

    Thanks

    Comment by Anthony — 22/04/2015 @ 14:54

  3. I like what you did for Android and Windows, but the iOS code uses IOKit, which is a private framework. Instead of using IOKit to get the MAC address, you could generated a GUID and store it in Keychain. It would persist across uninstall/reinstall and private a permanent GUID for that device.

    Take a look at Michael Ditum’s code in https://forums.xamarin.com/discussion/comment/4538/#Comment_4538, it can be dropped into your class pretty much as is.

    Comment by Chris Miller — 06/05/2015 @ 20:59

  4. I am still confused (for the IOS implementation above).
    Is the code listed above will “fail” if the App reinstalled (meaning return a new serial) or it is the “fixed” that will solve that particular problem (meaning the serial remain unchanged if the App is reinstalled).

    I am still having this issue, and need away to have IOS “serial” or Unique ID that never change if the App is reinstalled.

    Thank you!

    Comment by Reinhard Sual — 22/05/2015 @ 17:30

  5. Library (IOKit) missing since 10.8.2 update

    https://discussions.apple.com/thread/4345148?tstart=0

    Comment by Vitalii — 25/06/2015 @ 09:36

  6. Hi. Im a novice in the mobile dev. Why I cant just use get IMEI ?

    Comment by Andrey Beketov — 20/04/2016 @ 18:33

  7. Hai,

    how to get IMEI NUMBER in Xamarin crossplate form for android and ios windows phone

    Comment by ramabose — 25/01/2017 @ 15:57

  8. Gracias amigo, es lo que estaba buscando!!!

    Comment by Juan C — 22/06/2017 @ 03:27

RSS feed for comments on this post. TrackBack URL

Leave a Response