使用MonoTouch,检索iOS设备的设备序列号最简单的方法是什么?

3

MonoTouch是否有一种简单的机制来检索iOS设备的设备序列号(而不是UDID)?是否有第三方库可用于获取此信息?

如果有影响的话,我想在内部应用程序中使用此功能,并且不关心App Store的批准过程。


可能是重复的问题:如何以编程方式获取iPhone的序列号? - tc.
如果我在应用程序中访问iPhone序列号,是否允许在应用商店中?同样的问题可以在https://dev59.com/OlrUa4cB1Zd3GeqPkYHM找到。 - tc.
我特别寻找基于MonoTouch的解决方案,并且认为应该有比编写和绑定本地iOS库以获得单个函数更简单的方法来实现这一点。 - OpenAway
这是一个私有的C API。如果您可以链接IOKit(可能使用dlopen()动态链接库?)并从MonoTouch调用C函数,那么应该相当容易(我有印象C#可以轻松完成此操作),否则您需要编写一些本地代码或找到其他人来完成。此外,IME对象文件的兼容性经常会在iOS SDK的重大更新中出现问题,因此这样的库需要提供源代码或经常更新的二进制文件;对于无法放在应用商店的功能,后者似乎不值得。 - tc.
你能否使用不同的ID呢?或者你一定需要UUID吗?有一些其他的ID(例如广告ID http://developer.apple.com/library/ios/#documentation/AdSupport/Reference/ASIdentifierManager_Ref/ASIdentifierManager.html)可以使用,而且更受Xamarin和Apple的支持。 - jonathanpeppers
具体来说,我需要设备序列号,如果没有的话,需要另一个值,用户可以在新的iPad上轻松查找,而不需要使用下载的应用程序。 - OpenAway
1个回答

8

更新:从iOS 8开始,我们无法检索到iDevice的序列号。

要从Monotouch检索iPhone序列号,您可以使用以下技术:

  1. 从XCode创建静态库.a,其中包含获取序列号的函数
  2. 在MonoDevelop中创建绑定项目,将您的.a库绑定到C#类/函数中 (http://docs.xamarin.com/guides/ios/advanced_topics/binding_objective-c_libraries)
  3. 在您的应用程序中调用此绑定库(在步骤2中)。

详情如下:

步骤1. 在我的library.a中,我有一个DeviceInfo类,以下是获取序列号的实现:

#import "DeviceInfo.h"

#import <dlfcn.h>
#import <mach/port.h>
#import <mach/kern_return.h>
@implementation DeviceInfo

- (NSString *) serialNumber
{
    NSString *serialNumber = nil;

    void *IOKit = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW);
    if (IOKit)
    {
        mach_port_t *kIOMasterPortDefault = dlsym(IOKit, "kIOMasterPortDefault");
        CFMutableDictionaryRef (*IOServiceMatching)(const char *name) = dlsym(IOKit, "IOServiceMatching");
        mach_port_t (*IOServiceGetMatchingService)(mach_port_t masterPort, CFDictionaryRef matching) = dlsym(IOKit, "IOServiceGetMatchingService");
        CFTypeRef (*IORegistryEntryCreateCFProperty)(mach_port_t entry, CFStringRef key, CFAllocatorRef allocator, uint32_t options) = dlsym(IOKit, "IORegistryEntryCreateCFProperty");
        kern_return_t (*IOObjectRelease)(mach_port_t object) = dlsym(IOKit, "IOObjectRelease");

        if (kIOMasterPortDefault && IOServiceGetMatchingService && IORegistryEntryCreateCFProperty && IOObjectRelease)
        {
            mach_port_t platformExpertDevice = IOServiceGetMatchingService(*kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
            if (platformExpertDevice)
            {
                CFTypeRef platformSerialNumber = IORegistryEntryCreateCFProperty(platformExpertDevice, CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0);
                if (CFGetTypeID(platformSerialNumber) == CFStringGetTypeID())
                {
                    serialNumber = [NSString stringWithString:(__bridge NSString*)platformSerialNumber];
                    CFRelease(platformSerialNumber);
                }
                IOObjectRelease(platformExpertDevice);
            }
        }
        dlclose(IOKit);
    }

    return serialNumber;
}

@end

第二步。在我的Monotouch绑定库项目的ApiDefinition.cs中,我添加了以下绑定:

[BaseType (typeof (NSObject))]
    public interface DeviceInfo {
        [Export ("serialNumber")]
        NSString GetSerialNumber ();
    }

第三步。在我的应用程序中,我在第二步中导入了绑定库项目的引用,然后添加

using MyBindingProject;

...

string serialNumber = "";
            try {
                DeviceInfo nativeDeviceInfo = new DeviceInfo ();
                NSString temp = nativeDeviceInfo.GetSerialNumber();
                serialNumber = temp.ToString();
            } catch (Exception ex) {
                Console.WriteLine("Cannot get serial number {0} - {1}",ex.Message, ex.StackTrace);
            }

希望这有所帮助。如果您有任何问题,请不要犹豫。

我尝试了这段代码,在iOS7_beta上运行良好。但是,我不确定它是否会在不久的将来被弃用,或者IOKit.Framework DLL的可访问性是否会受到影响? 如果您找到有效链接,请回复。 - Meet
3
谢谢,我尝试了这个方法但在iOS 8 beta 5上崩溃了……还有其他适用于iOS 7和iOS 8的好方法吗?请给予建议。 - Meet
不,你无法在iOS8中获取序列号。 - Duyen-Hoa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接