如何在iOS8中使用IOKit获取设备的序列号,因为IOPlatformSerialNumber给出nil值

我想知道如何在iOS8中使用IOKit获取设备的序列号? 我使用了UIDevice+serialNumber ,我可以在iOS6和7中获得序列号。 在iOS8中, platformSerialNumber值在以下行中nil

 CFTypeRef platformSerialNumber = IORegistryEntryCreateCFProperty(platformExpertDevice,CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0); 

我正在使用: https : //gist.github.com/0xced/566994

注意:我的应用程序不会进入应用程序商店,它用于内部。 所以我正在寻找一些永远不会改变的具体事物,无论是字符串还是整数

从iOS 8开始,硬件信息(例如序列号)受到保护。 如果要检索此值,则必须使用私有权利对应用进行签名。 我不确定是否可以在企业应用程序中使用私有权利,它们肯定不能用于App Store应用程序,但这个问题用越狱标记,所以我将为此提供解决方案。

如果您希望序列号跟踪公司拥有的设备,我建议您利用Apple的移动设备管理(MDM)等服务。 这使您可以访问有关设备的大量信息,并允许您远程管理它们。

如果您只是在寻找一个永远不会因其他目的而改变的标识符,我建议您改用设备的UDID。 我能够在没有权利的情况下在我的设备上获得此function,但这可能是由于我的手机被越狱了。 其他人告诉我,事实上,权利是必需的。 有关这方面的更多信息,请访问iPhoneDevWiki 。

码:

 - (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"))); } 

待遇:

 com.apple.private.MobileGestalt.AllowedProtectedKeys  UniqueDeviceID  

提醒:这仅适用于非App Store应用程序(例如用于内部分发或越狱设备的应用程序)。 如果您将此代码提交给Apple,它将被拒绝。

以下是基于IOKit的方法,用于检索电池的序列号,该序列号是设备的良好静态唯一ID,在给定设备上的所有应用程序中都是相同的。 以下代码适用于iOS 8和9,但不适用于旧版本。

 - (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; } 

此代码需要一堆IOKit符号。 您可以包含必要的IOKit标头,但这可能有点痛苦。 假设您没有在其他地方使用IOKit,只需添加以下声明即可编译:

 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); 

现在,至于链接,你需要将IOKit.framework添加到你的应用程序中。 在大多数系统上,应该可以在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/IOKit.framework上找到它们。

我不知道如何在iOS8下获取序列号。 我很确定不再允许这样做。 Apple现在希望您使用ASIdentifierManager

 @property(nonatomic, readonly) NSUUID *advertisingIdentifier 

有关详细信息,请参阅https://developer.apple.com/library/prerelease/ios/documentation/AdSupport/Reference/ASIdentifierManager_Ref/index.html 。

注意:如果您使用此function,则会被拒绝,并且不会投放广告或更改应用内容以响应以前投放的广告。 我们做了以后,仍被拒绝,但后来在我们的提交说明中解释了我们使用它的确切内容(我们被接受了。)