Unique Identity for a Devices

I am building a cross platform application in which devices will communicate with a WCF Service. When a device connects to the service for the first time. I want to have a unique identifier for that device like a GUID and save information to a database. I wanted to use the IMEI but I am reading that iOS does not allow you to access that anymore. Is there a way to store something on the device itself that even if they delete your app and then install it again, you can use the same unique ID like a GUID or something such that when it connects to my service I can identify it as already connected before.

Answers

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Don't use the IEMI number. That's about to be considered private info.
    Don't re-invent the wheel. You're not the fist person to need this.
    THere is already an unique device ident number for this purpose out there.
    CHeck the hundred or so threads already on the forum: I know this has been discussed before, and within the last month

  • seanydaseanyda GBMember ✭✭✭✭✭

    As far as I'm aware (for iOS anyway) there isn't anything you can use to uniquely identify the device (which would pass an apple review process). You can uniquely identify an "instance" of an installed app but once the app is deleted and reinstalled, it's not possible to carry any data over. All data is deleted along with the app.

  • KhilbornKhilborn Member ✭✭

    @ClintStLaurent said:
    Don't use the IEMI number. That's about to be considered private info.
    Don't re-invent the wheel. You're not the fist person to need this.
    THere is already an unique device ident number for this purpose out there.
    CHeck the hundred or so threads already on the forum: I know this has been discussed before, and within the last month

    Care to link any of these 100's of threads you're talking about?

  • JohnHJohnH GBMember ✭✭✭✭✭

    @Khilborn said:

    @ClintStLaurent said:
    Don't use the IEMI number. That's about to be considered private info.
    Don't re-invent the wheel. You're not the fist person to need this.
    THere is already an unique device ident number for this purpose out there.
    CHeck the hundred or so threads already on the forum: I know this has been discussed before, and within the last month

    Care to link any of these 100's of threads you're talking about?

    I didn't know the answer to this question either, so I took Clint's advice and used the search option. Yup, found the answer in about 2 minutes. Thank you @ClintStLaurent!

  • KhilbornKhilborn Member ✭✭
    edited July 2018

    https://github.com/jamesmontemagno/DeviceInfoPlugin>; @FabricioBertani said:

    Will this work with IOS such that Apple wont reject my app since this gets the ID?

  • JohnHJohnH GBMember ✭✭✭✭✭

    @Khilborn said:
    https://github.com/jamesmontemagno/DeviceInfoPlugin>; @FabricioBertani said:

    Will this work with IOS such that Apple wont reject my app since this gets the ID?

    Did you not see this bit in the details?

    Id This should not be used as a stable ID as each vendor on Android may or may not set it to a different value and on iOS it is changed when applications are uninstalled.

  • KhilbornKhilborn Member ✭✭

    @JohnHair said:

    @Khilborn said:
    https://github.com/jamesmontemagno/DeviceInfoPlugin>; @FabricioBertani said:

    Will this work with IOS such that Apple wont reject my app since this gets the ID?

    Did you not see this bit in the details?

    Id This should not be used as a stable ID as each vendor on Android may or may not set it to a different value and on iOS it is changed when applications are uninstalled.

    Missed it, Thanks

    John, do you happen to know if I would be able to create a UUID and store it to the phone such that it remain even if a user uninstalls my app?

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    if I would be able to create a UUID and store it to the phone such that it remain even if a user uninstalls my app?

    No offense... But I don't think that's your call, good practice or acceptable behavior for an app.
    If the user uninstalls your app you shouldn't be leaving things behind. They don't want your app. Accept that.

  • KhilbornKhilborn Member ✭✭
    edited July 2018

    @ClintStLaurent said:

    if I would be able to create a UUID and store it to the phone such that it remain even if a user uninstalls my app?

    No offense... But I don't think that's your call, good practice or acceptable behavior for an app.
    If the user uninstalls your app you shouldn't be leaving things behind. They don't want your app. Accept that.

    Fair enough. I am asking because what my company wants to do is set Licenses for use. What I mean by that, the type of business we are in will buy tiered packages that will allow x amount of machines to connect to server. We are now getting in to the app world and want to do the same thing. A customer could buy a package that only allows 1000 devices to connect to the server. Can that be controlled on the server side or pretty much no? The server would have to control it and need to identify each device in order to do it I believe.

    Or can an App capture an event from say some service on the android when your app is going to be uninstalled to communicate say with my server?

  • KhilbornKhilborn Member ✭✭
    edited July 2018

    So basically I think I have this figured out. I will use the firebase token to identify devices. With that I will be able to track uninstalls. For Android sending blanks push notification and if I get a NotRegistered from the GCM I know a user removed the app from their device and can clean up my database. AS for iOS, I will use the APN to let me know if a device is no longer registered and then clean up the database accordingly.

  • SreeeeSreeee INMember ✭✭✭✭✭

    I found a solution for this feature here. Also please refer the StackOverflow thread related to this.

  • Junior_OliveiraJunior_Oliveira USMember ✭✭

    I really need help too.

    I looked these links:

    @Sreeee said:
    I found a solution for this feature here. Also please refer the StackOverflow thread related to this.

    However these methods are highlighted as unstable, or not advised:

    https://github.com/xamarin/Essentials/issues/608

    Since there is not stable API across all platforms this means that Xamarin.Essentials can not provide this API to developers for such a critical part of their application

    Is here:

    https://montemagno.com/unique-device-id-for-mobile-apps/

    The answer is actually pretty straight forward: There is truly no consistent API across every platform to deliver an identifier that is unique to the device or application.

    And here too:
    https://developer.android.com/training/articles/user-data-ids

    1: Avoid using hardware identifiers. In most use cases, you can avoid using hardware identifiers, such as SSAID (Android ID) and IMEI, without limiting required functionality.

    3: Use an Instance ID or a privately stored GUID whenever possible for all other use cases, except for payment fraud prevention and telephony. For the vast majority of non-ads use cases, an Instance ID or GUID should be sufficient.

    Okay, using a GUID locally. How then can I resolve this situation, please:

    In my application, the user creates an account and when buying the Pro package he has the right to use Pro features on two devices. To control this, I can use a GUID created on the first use of the application, as well as the device model.

    But if the user uninstall the application and reinstall, a new GUID will be generated, as you already noticed.

    For my web service will be a new device, even if the model of the device is the same. This is my big question, how to identify that it is not a new device, but an application reinstallation?

  • SreeeeSreeee INMember ✭✭✭✭✭

    Hi @Junior_Oliveira It is worked for me on android. still, I didn't test it in ios.

    In PCL create an interface IDevice
    IDevice.cs

    namespace projectname
    {
        public interface IDevice
        {
           string GetIdentifier();
        }
    }
    

    In android project create a class AndroidDevice
    AndroidDevice.cs

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

    In IOS project create a class IOSDevice
    IOSDevice.cs

    [assembly: Xamarin.Forms.Dependency(typeof(IOSDevice))]
    namespace projectname.iOS
    {
        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);
                        //serial = UIDevice.CurrentDevice.IdentifierForVendor.ToString();
                    }
                    IOObjectRelease(platformExpert);
                }
                return serial;
            }
        }
    }
    

    Capture the unique id of a device in PCL using the following code, where deviceIdentifier is the unique id.

    IDevice device = DependencyService.Get<IDevice>();
        string deviceIdentifier = "";
        if (device != null)
        {
           deviceIdentifier = device.GetIdentifier();
         }
         Debug.WriteLine("deviceIdentifier:>>" + deviceIdentifier);
    

    NB: I didn't test this feature in ios. Hope this helps you :)

  • AMNishanthiKumariAMNishanthiKumari USMember ✭✭✭

    @Sreeee I tried your code. i am getting this errors

  • SreeeeSreeee INMember ✭✭✭✭✭

    @AMNishanthiKumari
    What errors you are facing?
    Did you create an interface(IDevice.cs) in PCL project?

  • AMNishanthiKumariAMNishanthiKumari USMember ✭✭✭
    edited June 12

    yeh i had created it

  • AMNishanthiKumariAMNishanthiKumari USMember ✭✭✭
    edited June 12

    errors are red color highlighted

  • SreeeeSreeee INMember ✭✭✭✭✭

    @AMNishanthiKumari

    Please share your complete code?

  • AMNishanthiKumariAMNishanthiKumari USMember ✭✭✭
    edited June 12

    here i attached

  • SreeeeSreeee INMember ✭✭✭✭✭

    @AMNishanthiKumari I checked your project, It is working fine in PCL project, but not in .Net project. Can you please start a new thread for this issue?

  • AMNishanthiKumariAMNishanthiKumari USMember ✭✭✭
  • SreeeeSreeee INMember ✭✭✭✭✭

    @Junior_Oliveira and @AMNishanthiKumari

    I tested the unique id code in iPhone and it is not working.

    For ios please use the following code for getting the unique id.

    [assembly: Xamarin.Forms.Dependency(typeof(IOSDevice))]
    namespace projectname.iOS
    {
        public class IOSDevice : IDevice
        {
         public string GetIdentifier()
            {
                    var query = new SecRecord(SecKind.GenericPassword);
                    query.Service = NSBundle.MainBundle.BundleIdentifier;
                    query.Account = "UniqueID";
    
                    NSData uniqueId = SecKeyChain.QueryAsData(query);
                    if(uniqueId == null) {
                            query.ValueData = NSData.FromString(System.Guid.NewGuid().ToString());
                            var err = SecKeyChain.Add (query);
                            if (err != SecStatusCode.Success && err != SecStatusCode.DuplicateItem)
                                    throw new Exception("Cannot store Unique ID");
                            return query.ValueData.ToString();
                    }
                    else 
                    {
                            return uniqueId.ToString();
                    }
                  }
              }
            }
    

    I found this solution here.

  • AMNishanthiKumariAMNishanthiKumari USMember ✭✭✭

    @Sreeee Thanks for your post.

  • Junior_OliveiraJunior_Oliveira USMember ✭✭

    Thank you!!!

Sign In or Register to comment.