我需要在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也受到影响.