在iOS 5.1中获取CellID,MCC,MNC,LAC和网络

我需要在iOS 5.1(iPhone 4S)中检索当前服务单元塔的CellID,MCC,MNC,LAC和网络(GSM,3G).我知道这些信息是可用的,因为我可以在FieldTest模式下看到它(在呼叫* 3001#12345#*后可访问).我想它可以通过私人/未记录的iOS框架访问.

iphone,check values of cellId / Lac的问题中,作者表示我可以在iOS上收到radioId信息cellId,Lac,但是没有提供有关如何做的信息.

有人可以告诉我如何获得这个信息?

解决方法

我知道如何在iOS 5.x – 7.x上执行三种方法.所有这些都使用CoreTelephony.framework的私有API.支持GSM和UMTS.

1)使用单元监视器

struct CTResult
{
    int flag;
    int a;
};

extern CFStringRef const kCTCellMonitorCellType;
extern CFStringRef const kCTCellMonitorCellTypeServing;
extern CFStringRef const kCTCellMonitorCellTypeNeighbor;
extern CFStringRef const kCTCellMonitorCellId;
extern CFStringRef const kCTCellMonitorLAC;
extern CFStringRef const kCTCellMonitorMCC;
extern CFStringRef const kCTCellMonitorMNC;
extern CFStringRef const kCTCellMonitorUpdateNotification;

id _CTServerConnectionCreate(CFAllocatorRef,void*,int*);
void _CTServerConnectionAddToRunLoop(id,CFRunLoopRef,CFStringRef);

#ifdef __LP64__

void _CTServerConnectionRegisterForNotification(id,CFStringRef);
void _CTServerConnectionCellMonitorStart(id);
void _CTServerConnectionCellMonitorStop(id);
void _CTServerConnectionCellMonitorCopyCellInfo(id,CFArrayRef*);

#else

void _CTServerConnectionRegisterForNotification(struct CTResult*,id,CFStringRef);
#define _CTServerConnectionRegisterForNotification(connection,notification) { struct CTResult res; _CTServerConnectionRegisterForNotification(&res,connection,notification); }

void _CTServerConnectionCellMonitorStart(struct CTResult*,id);
#define _CTServerConnectionCellMonitorStart(connection) { struct CTResult res; _CTServerConnectionCellMonitorStart(&res,connection); }

void _CTServerConnectionCellMonitorStop(struct CTResult*,id);
#define _CTServerConnectionCellMonitorStop(connection) { struct CTResult res; _CTServerConnectionCellMonitorStop(&res,connection); }

void _CTServerConnectionCellMonitorCopyCellInfo(struct CTResult*,CFArrayRef*);
#define _CTServerConnectionCellMonitorCopyCellInfo(connection,tmp,cells) { struct CTResult res; _CTServerConnectionCellMonitorCopyCellInfo(&res,cells); }

#endif

id CTConnection = _CTServerConnectionCreate(NULL,CellMonitorCallback,NULL);
_CTServerConnectionAddToRunLoop(CTConnection,CFRunLoopGetCurrent(),kCFRunLoopCommonModes);
_CTServerConnectionRegisterForNotification(CTConnection,kCTCellMonitorUpdateNotification);
_CTServerConnectionCellMonitorStart(CTConnection);

int CellMonitorCallback(id connection,CFStringRef string,CFDictionaryRef dictionary,void *data)
{
    int tmp = 0;
    CFArrayRef cells = NULL;
    _CTServerConnectionCellMonitorCopyCellInfo(connection,(void*)&tmp,&cells);
    if (cells == NULL)
    {
        return 0;
    }

    for (NSDictionary* cell in (NSArray*)cells)
    {
        int LAC,CID,MNC;

        if ([cell[(NSString*)kCTCellMonitorCellType] isEqualToString:(NSString*)kCTCellMonitorCellTypeServing])
        {
            LAC = [cell[(NSString*)kCTCellMonitorLAC] intValue];
            CID = [cell[(NSString*)kCTCellMonitorCellId] intValue];
            MCC = [cell[(NSString*)kCTCellMonitorMCC] intValue];
            MNC = [cell[(NSString*)kCTCellMonitorMNC] intValue];
        }
        else if ([cell[(NSString*)kCTCellMonitorCellType] isEqualToString:(NSString*)kCTCellMonitorCellTypeNeighbor])
        {
        }
    }

    CFRelease(cells);

    return 0;
}

2)使用CTTelephonyCenter

kCTRegistrationCellChangedNotification每当当前的服务小区塔更改时发送.

extern CFStringRef const kCTRegistrationCellChangedNotification;
extern CFStringRef const kCTRegistrationGsmLac;
extern CFStringRef const kCTRegistrationLac;
extern CFStringRef const kCTRegistrationGsmCellId;
extern CFStringRef const kCTRegistrationCellId;

CFStringRef CTSIMSupportCopyMobileSubscriberCountryCode(CFAllocatorRef);
CFStringRef CTSIMSupportCopyMobileSubscriberNetworkCode(CFAllocatorRef);

id CTTelephonyCenterGetDefault();
void CTTelephonyCenterAddObserver(id,void,CFNotificationCallback,CFStringRef,CFNotificationSuspensionBehavior);

CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(),NULL,callback,CFNotificationSuspensionBehaviorHold);

void callback(CFNotificationCenterRef center,void *observer,CFStringRef name,const void *object,CFDictionaryRef userInfo)
{
    NSString* notification = (NSString*)name;
    NSDictionary *cellInfo = (NSDictionary*)userInfo;

    if ([notification isEqualToString:(NSString*)kCTRegistrationCellChangedNotification])
    {
        int LAC,MNC;

        if (cellInfo[(NSString*)kCTRegistrationGsmLac])
        {
            LAC = [cellInfo[(NSString*)kCTRegistrationGsmLac] intValue];
        }
        else if (data[(NSString*)kCTRegistrationLac])
        {
            LAC = [cellInfo[(NSString*)kCTRegistrationLac] intValue];
        }

        if (cellInfo[(NSString*)kCTRegistrationGsmCellId])
        {
            CID = [cellInfo[(NSString*)kCTRegistrationGsmCellId] intValue];
        }
        else if (cellInfo[(NSString*)kCTRegistrationCellId])
        {
            CID = [cellInfo[(NSString*)kCTRegistrationCellId] intValue];
        }

        MCC = [[(NSString*)CTSIMSupportCopyMobileSubscriberCountryCode(NULL) autorelease] intValue];
        MNC = [[(NSString*)CTSIMSupportCopyMobileSubscriberNetworkCode(NULL) autorelease] intValue];
    }
}

3)这返回当前服务的单元塔

struct CTResult
{
    int flag;
    int a;
};

id _CTServerConnectionCreate(CFAllocatorRef,int*);

#ifdef __LP64__

void _CTServerConnectionGetLocationAreaCode(id,int*);
void _CTServerConnectionGetCellID(id,int*);

#else

void _CTServerConnectionGetLocationAreaCode(struct CTResult*,int*);
#define _CTServerConnectionGetLocationAreaCode(connection,LAC) { struct CTResult res; _CTServerConnectionGetLocationAreaCode(&res,LAC); }

void _CTServerConnectionGetCellID(struct CTResult*,int*);
#define _CTServerConnectionGetCellID(connection,CID) { struct CTResult res; _CTServerConnectionGetCellID(&res,CID); }

#endif

int CID,LAC,MNC;

id CTConnection = _CTServerConnectionCreate(NULL,NULL);
_CTServerConnectionGetCellID(CTConnection,&CID);
_CTServerConnectionGetLocationAreaCode(CTConnection,&LAC);
MCC = [[(NSString*)CTSIMSupportCopyMobileSubscriberCountryCode(NULL) autorelease] intValue];
MNC = [[(NSString*)CTSIMSupportCopyMobileSubscriberNetworkCode(NULL) autorelease] intValue];

UPDATE

在ARM64(iPhone 5S)上,所有CoreTelephony函数都接受struct CTResult参数的问题.显然,64位版本的CoreTelephony导出这些函数,而没有结构化的CTResult参数.因为如果你像以前一样调用这些函数,那么你将会在ARM64中收到错误 – 参数会出错.我更新了函数声明,使它们可以在32位和64位ARM架构上工作.我测试了它,它适用于iPhone 4S和iPhone 5S.

这仅适用于ARM64.如果您为32位ARM架构构建项目,那么就没有这样的问题.您的应用程序将使用32位版本的CoreTelephony,该版本需要使用struct CTResult参数.

8.3更新

从iOS 8.3起,所有上述解决方案都需要授权才能工作

<key>com.apple.CommCenter.fine-grained</key>
<array>
    <string>spi</string>
</array>

不仅单元监视器受到保护,而且似乎所有CoreTelephony通知现在都要求该权限工作.例如,kCTMessageReceivedNotification也受到影响.

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...