I was wondered to know how to get serial number of a device using IOKit
in iOS8? I used UIDevice+serialNumber
and I am able to get serial number in iOS6 and7. In iOS8 value of platformSerialNumber
is coming nil
in the following line:
CFTypeRef platformSerialNumber = IORegistryEntryCreateCFProperty(platformExpertDevice,CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0);
I am using : https://gist.github.com/0xced/566994
Note:My app will not go to app store, its for inhouse. So I am looking for something more concrete that will never change, either String or integer
Starting in iOS 8, hardware information, such as the serial number, is protected. If you want to retrieve this value, you must sign your app with private entitlements. I'm not sure if it's possible to use private entitlements in enterprise apps, and they certainly can't be used for App Store apps, but this question is tagged with jailbreak so I'll provide a solution for that.
If you want the serial number to track devices your company owns, I'd recommend taking advantage of a service like Apple's mobile device management (MDM). This gives you access to a large amount of information about devices, and allows you to manage them remotely.
If you're simply looking for an identifier that will never change for other purposes, I'd recommend using the device's UDID instead. I was able to get this on my device without entitlements, however that may be due to my phone being jailbroken. I've been told by others that entitlements are, in fact, required. More information about this can be found on the iPhoneDevWiki.
Code:
- (NSString *)udid
{
void *gestalt = dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_GLOBAL | RTLD_LAZY);
CFStringRef (*MGCopyAnswer)(CFStringRef) = (CFStringRef (*)(CFStringRef))(dlsym(gestalt, "MGCopyAnswer"));
return CFBridgingRelease(MGCopyAnswer(CFSTR("UniqueDeviceID")));
}
Entitlements:
<key>com.apple.private.MobileGestalt.AllowedProtectedKeys</key>
<array>
<string>UniqueDeviceID</string>
</array>
Reminder: This is only applicable to non-App Store apps (such as those intended for in-house distribution, or for jailbroken devices). If you submit this code to Apple it WILL get rejected.
The following is an IOKit-based approach that retrieves the battery's serial number, which is a good static, unique ID for the device that will be the same across all apps on a given device. The following code works for iOS 8 and 9, but will not work for older versions.
- (NSString *) deviceUniqueID
{
mach_port_t iokitPort = 0;
CFMutableDictionaryRef properties;
IOMasterPort(0, &iokitPort);
CFDictionaryRef serviceName = IOServiceNameMatching("charger");
io_service_t service = IOServiceGetMatchingService(iokitPort, serviceName);
if (service == 0)
return nil;
kern_return_t status = IORegistryEntryCreateCFProperties(service,
&properties,
kCFAllocatorDefault,
kNilOptions);
IOObjectRelease(service);
if (status == KERN_SUCCESS)
{
NSDictionary *dict = (__bridge NSDictionary *)(properties);
NSData *batteryIDData = dict[@"battery-id"];
CFRelease(properties);
if ([batteryIDData isKindOfClass: [NSData class]])
return [NSString stringWithUTF8String:[batteryIDData bytes]];
}
return nil;
}
This code requires a bunch of IOKit symbols. You could include the necessary IOKit headers, but that can be a bit of a pain. Assuming you're not using IOKit elsewhere, just add the following declarations and it should compile fine:
typedef mach_port_t io_object_t;
typedef io_object_t io_registry_entry_t;
typedef io_object_t io_iterator_t;
typedef io_object_t io_connect_t;
typedef io_object_t io_service_t;
typedef UInt32 IOOptionBits;
kern_return_t IOMasterPort(mach_port_t bootstrapPort, mach_port_t *masterPort);
CFMutableDictionaryRef IOServiceNameMatching( const char *name );
io_service_t IOServiceGetMatchingService ( mach_port_t masterPort, CFDictionaryRef matching );
kern_return_t IORegistryEntryCreateCFProperties(io_registry_entry_t entry,
CFMutableDictionaryRef *properties,
CFAllocatorRef allocator,
IOOptionBits options);
kern_return_t IOObjectRelease (io_object_t object);
Now, as for getting it to link, you will need to add the IOKit.framework into your app. On most systems it should be available at /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/IOKit.framework
I don't know how to get the serial number under iOS8. I'm pretty sure it is no longer permitted. Apple now wants you to use the ASIdentifierManager's
@property(nonatomic, readonly) NSUUID *advertisingIdentifier
See https://developer.apple.com/library/prerelease/ios/documentation/AdSupport/Reference/ASIdentifierManager_Ref/index.html for more detail.
Note: You will get rejected if you use this and either don't serve ads or change the apps behavior in response to a previously served ad. We do the later, got rejected still, but then explained in our submission notes exactly what we use it for (and we were accepted.)