如何获得ios设备中的硬件信息(下)

来源:互联网 发布:马哥linux 编辑:程序博客网 时间:2024/04/28 10:49

      上篇博文提到了ios 还可以通过其他方法获得更多的硬件信息,例如mac地址,电池电量,序列号,IMIE,总磁盘大小,背光等等,现贴出我已经测试通过的程序,获取IMIE,mac地址和序列号。

首先,引入libIOkit 的两个库文件,然后可以创建UIDevice 的catagroy。

具体代码如下:

#import "network.h"
#include <sys/types.h>
#include <sys/sysctl.h>
#import <mach/mach_host.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <ifaddrs.h>

#if SUPPORTS_IOKIT_EXTENSIONS
#pragma mark IOKit miniheaders

#define kIODeviceTreePlane        "IODeviceTree"

enum {
    kIORegistryIterateRecursively    = 0x00000001,
    kIORegistryIterateParents        = 0x00000002
};

typedef mach_port_t    io_object_t;
typedef io_object_t    io_registry_entry_t;
typedef char        io_name_t[128];
typedef UInt32        IOOptionBits;

CFTypeRef
IORegistryEntrySearchCFProperty(
                                io_registry_entry_t    entry,
                                const io_name_t        plane,
                                CFStringRef        key,
                                CFAllocatorRef        allocator,
                                IOOptionBits        options );

kern_return_t
IOMasterPort( mach_port_t    bootstrapPort,
             mach_port_t *    masterPort );

io_registry_entry_t
IORegistryGetRootEntry(
                       mach_port_t    masterPort );

CFTypeRef
IORegistryEntrySearchCFProperty(
                                io_registry_entry_t    entry,
                                const io_name_t        plane,
                                CFStringRef        key,
                                CFAllocatorRef        allocator,
                                IOOptionBits        options );

kern_return_t   mach_port_deallocate
(ipc_space_t                               task,
 mach_port_name_t                          name);


@implementation UIDevice (IOKit_Extensions)
#pragma mark IOKit Utils
NSArray *getValue(NSString *iosearch)
{
    mach_port_t          masterPort;
    CFTypeID             propID = (CFTypeID) NULL;
    unsigned int         bufSize;
    
    kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
    if (kr != noErr) return nil;
    
    io_registry_entry_t entry = IORegistryGetRootEntry(masterPort);
    if (entry == MACH_PORT_NULL) return nil;
    
    CFTypeRef prop = IORegistryEntrySearchCFProperty(entry, kIODeviceTreePlane, (CFStringRef) iosearch, nil, kIORegistryIterateRecursively);
    if (!prop) return nil;
    
    propID = CFGetTypeID(prop);
    if (!(propID == CFDataGetTypeID()))
    {
        mach_port_deallocate(mach_task_self(), masterPort);
        return nil;
    }
    
    CFDataRef propData = (CFDataRef) prop;
    if (!propData) return nil;
    
    bufSize = CFDataGetLength(propData);
    if (!bufSize) return nil;
    
    //NSString *p1 = [[[NSString alloc] initWithBytes:CFDataGetBytePtr(propData) length:bufSize encoding:1] autorelease];
    NSString *p1 = [[[NSString alloc] initWithBytes:CFDataGetBytePtr(propData) length:bufSize encoding:NSUTF8StringEncoding] autorelease];
    mach_port_deallocate(mach_task_self(), masterPort);
    return [p1 componentsSeparatedByString:@"/0"];
}

- (NSString *) imei
{
    NSArray *results = getValue(@"device-imei");
    if (results)
    {
        //return [results objectAtIndex:0];
        NSString *string_content = [results objectAtIndex:0];
        const char *char_content = [string_content UTF8String];
        return  [[NSString alloc] initWithCString:(const char*)char_content  encoding:NSUTF8StringEncoding];
        
    }
    //if(results)
    //{
    //    return [(NSString *)[results objectAtIndex:0] substringToIndex:2];
   // }
    return @"";
}

- (NSString *) serialnumber
{
    NSArray *results = getValue(@"serial-number");
    if (results) return [results objectAtIndex:0];
    return nil;
}

- (NSString *) backlightlevel
{
    NSArray *results = getValue(@"backlight-level");
    if (results) return [results objectAtIndex:0];
    return nil;
}

- (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 error/n");
        return NULL;
    }
    
    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1/n");
        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");
        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 uppercaseString];
}



@end
#endif

这样就可以分别得到IMEI,序列号,背光和mac 地址。但是有时我们会想得到手机的运营商,这时候我们可以从IMSI中获取到,具体获取IMSI的方法,到目前为止还没有一个官方的api,我们一般都是从越狱后,使用toolchain获得了imsi,但是这个可能没有办法获得app store 的审核,所以可操作性不强,但是还是记录下从imsi中获取手机运营商的方法如下:

MSI共有15位,其结构如下:

MCC+MNC+MSIN ,(MNC+MSIN=NMSI

MCCMobile Country Code,移动国家码,MCC的资源由国际电联(ITU)统一分配和管理,唯一识别移动用户所属的国家,共3位,中国为460;

MNC:Mobile Network Code,移动网络码,共2位,中国移动TD系统使用00,中国联通GSM系统使用01,中国移动GSM系统使用02,中国电信CDMA系统使用03,一个典型的IMSI号码为460030912121001;

MSIN:Mobile Subscriber Identification Number共有10位,其结构如下:

09+M0M1M2M3+ABCD

其中的M0M1M2M3MDN号码中的H0H1H2H3可存在对应关系,ABCD四位为自由分配。

这样就可以依据IMSI中的MCCMNC来确定运营商了。当然知道编码规则同时还是需要知道对应编码的的国家和网络了。

 

 

实现的代码如下:

/* China - CN
 * MCC    MNC    Brand    Operator                Status        Bands (MHz)                                    References and notes
 * 460    00            China Mobile            Operational    GSM 900/GSM 1800 UMTS (TD-SCDMA) 1880/2010
 * 460    01            China Unicom            Operational    GSM 900/GSM 1800/ UMTS 2100                    CDMA network sold to China Telecom, WCDMA commercial trial started in May 2009 and in full commercial operation as of October 2009.
 * 460    02            China Mobile            Operational    GSM 900/GSM 1800/ UMTS (TD-SCDMA) 1880/2010   
 * 460    03            China Telecom            Operational    CDMA 800/cdma evdo 2100   
 * 460    05            China Telecom            Operational       
 * 460    06            China Unicom            Operational    GSM 900/GSM 1800/UMTS 2100   
 * 460    07            China Mobile            Operational    GSM 900/GSM 1800/UMTS (TD-SCDMA) 1880/2010   
 * 460    20            China Tietong            Operational    GSM-R   
 * NA    NA            China Telecom&China Unicom    Operational       
 */
+ (NSString*)getCarrier:(NSString*)imsi
{
    if (imsi == nil || [imsi isEqualToString:@"SIM Not Inserted"] ) {
        return @"Unknown";
    }
    else {
        if ([[imsi substringWithRange:NSMakeRange(0, 3)] isEqualToString:@"460"]) {
            NSInteger MNC = [[imsi substringWithRange:NSMakeRange(3, 2)] intValue];
            switch (MNC) {
                case 00:
                case 02:
                case 07:
                    return @"China Mobile";
                    break;
                case 01:
                case 06:   
                    return @"China Unicom";
                    break;
                case 03:
                case 05:   
                    return @"China Telecom";
                    break;
                case 20:
                    return @"China Tietong";
                    break;
                default:
                    break;
            }
        }
    }
    return @"Unknown";
}


最后想要获得更多的手机硬件信息,可以参考一下的地址查看

分享个人ios开发练手之作,显示ios设备信息的程序





原创粉丝点击