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