All Things Mobile

The Latest News & Knowledge

Create Your Own Unique Device Identifier (UDID)

Apple may have deprecated the UDID but that doesn’t mean it isn’t possible to unqiuely identify a device to your app. The most important thing about a custom UDID is ensuring uniqueness. Each device has a phyical MAC (Media Access Control) that is globally unique. If we base our custom UDID on the MAC address we can ensure uniqueness.



At Rade | Eccles we create an MD5 hash based on the MAC address and the bundle identifier. This gives us a unique ID for a device/app combination. In some instances we need a UDID that is global across multiple apps. In those cases we create the hash only based on the MAC address, not the bundle identifier.



We implement this functionality as a category on UIDevice which helps to mimic the original native functionality. The actual implementation looks like this:


[[UIDevice currentDevice] uniqueDeviceIdentifier]


To achieve this functionality simply add the following code to your project and include UIDevice+IdentifierAddition.h in the appropriate locations:



UIDevice+IdentifierAddition.h

   //
   // UIDevice(Identifier).h
   // UIDeviceAddition
   //
   // Created by Georg Kitz on 20.08.11.
   // Copyright 2011 Aurora Apps. All rights reserved.
   //
   
   #import 
   
   
   @interface UIDevice (IdentifierAddition)
   
   /*
   * @method uniqueDeviceIdentifier
   * @description use this method when you need a unique identifier in one app.
   * It generates a hash from the MAC-address in combination with the bundle identifier
   * of your app.
   */

   - (NSString *) uniqueDeviceIdentifier;
   
   /*
   * @method uniqueDeviceIdentifier
   * @description use this method when you need a unique global identifier to track a device
   * with multiple apps. as example a advertising network will use this method to track the device
   * from different apps.
   * It generates a hash from the MAC-address only.
   */
   
   - (NSString *) uniqueGlobalDeviceIdentifier;
   
   @end



UIDevice+IdentifierAddition.m

   //
   //  UIDevice(Identifier).m
   //  UIDeviceAddition
   //
   //  Created by Georg Kitz on 20.08.11.
   //  Copyright 2011 Aurora Apps. All rights reserved.
   //
    
   #import "UIDevice+IdentifierAddition.h"
   #import "NSString+MD5Addition.h"
    
   #include  // Per msqr>
   #include 
   #include 
   #include 
 
   @interface UIDevice(Private)<

   - (NSString *) macaddress;

   @end
  
   @implementation UIDevice (IdentifierAddition)

   ////////////////////////////////////////////////////////////////////////////////
   #pragma mark -
   #pragma mark Private Methods

   // Return the local MAC addy
   // Courtesy of FreeBSD hackers email list
   // Accidentally munged during previous update. Fixed thanks to erica sadun & mlamb.
   - (NSString *) macaddress{

    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;

    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;
      
    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex errorn");
        return NULL;
    }

    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1n");
        return NULL;
    }
     
    if ((buf = malloc(len)) == NULL) {
        printf("Could not allocate memory. error!n");
        return NULL;

} if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {< printf("Error: sysctl, take 2"); free(buf); return NULL;< } ifm = (struct if_msghdr *)buf; sdl = (struct sockaddr_dl *)(ifm + 1); ptr = (unsigned char *)LLADDR(sdl); NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)]; free(buf); return outstring; } //////////////////////////////////////////////////////////////////////////////// #pragma mark - #pragma mark Public Methods - (NSString *) uniqueDeviceIdentifier{ NSString *macaddress = [[UIDevice currentDevice] macaddress]; NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; NSString *stringToHash = [NSString stringWithFormat:@"%@%@",macaddress,bundleIdentifier]; NSString *uniqueIdentifier = [stringToHash stringFromMD5]; return uniqueIdentifier; } - (NSString *) uniqueGlobalDeviceIdentifier{ NSString *macaddress = [[UIDevice currentDevice] macaddress]; NSString *uniqueIdentifier = [macaddress stringFromMD5]; return uniqueIdentifier; } @end



NSString+MD5Addition.h

   #import 
  
   @interface NSString(MD5Addition)
   
   - (NSString *) stringFromMD5;
   
   @end

NSString+MD5Addition.m

   #import "NSString+MD5Addition.h"
   #import 
 
   @implementation NSString(MD5Addition)
 
   - (NSString *) stringFromMD5{
    
       if(self == nil || [self length] == 0)
           return nil;
   
      const char *value = [self UTF8String];
 
      unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH];
      CC_MD5(value, strlen(value), outputBuffer);
 
      NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
      for(NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++){
          [outputString appendFormat:@"%02x",outputBuffer[count]];
      }
   
      return [outputString autorelease];
  }
   
  @end


One final note... we did not create this class. It was found on the web. The comments are attributed to Georg Kitz on August 20th, 2011. We appreciate Georg sharing this useful code.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>