我需要检索iOS 5.1(iPhone 4S)中当前服务细胞塔的CellID,MCC,MNC,LAC和网络(GSM,3G)。我知道这些信息是可用的,因为我可以在FieldTest模式下看到它(在调用**** 3001#12345#****后可访问)。我想它可以通过私有/未记录的iOS框架访问。
在问题iphone, check values of cellId / Lac中,作者指出我可以在iOS上获取无线电信息cellId,Lac,MNC,MCC ,但是没有提供有关如何执行此操作的信息。
有人能告诉我如何获取此信息吗?
答案 0 :(得分:17)
我知道如何在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, void*, 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*, id, void*, CFArrayRef*);
#define _CTServerConnectionCellMonitorCopyCellInfo(connection, tmp, cells) { struct CTResult res; _CTServerConnectionCellMonitorCopyCellInfo(&res, connection, tmp, 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, MCC, 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, void, CFNotificationSuspensionBehavior);
...
CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, callback, NULL, NULL, 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, CID, MCC, 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, void*, int*);
#ifdef __LP64__
void _CTServerConnectionGetLocationAreaCode(id, int*);
void _CTServerConnectionGetCellID(id, int*);
#else
void _CTServerConnectionGetLocationAreaCode(struct CTResult*, id, int*);
#define _CTServerConnectionGetLocationAreaCode(connection, LAC) { struct CTResult res; _CTServerConnectionGetLocationAreaCode(&res, connection, LAC); }
void _CTServerConnectionGetCellID(struct CTResult*, id, int*);
#define _CTServerConnectionGetCellID(connection, CID) { struct CTResult res; _CTServerConnectionGetCellID(&res, connection, CID); }
#endif
...
int CID, LAC, MCC, MNC;
id CTConnection = _CTServerConnectionCreate(NULL, NULL, NULL);
_CTServerConnectionGetCellID(CTConnection, &CID);
_CTServerConnectionGetLocationAreaCode(CTConnection, &LAC);
MCC = [[(NSString*)CTSIMSupportCopyMobileSubscriberCountryCode(NULL) autorelease] intValue];
MNC = [[(NSString*)CTSIMSupportCopyMobileSubscriberNetworkCode(NULL) autorelease] intValue];
<强>更新强>
在ARM64(iPhone 5S)上,所有接受struct CTResult
参数的CoreTelephony函数都存在问题。显然,64位版本的CoreTelephony在没有struct 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
也受到影响。
答案 1 :(得分:2)
suscriberCellularProvider是一种对象方法(vs class method)。
您可以在此处查看如何使用它: Determine iPhone user's country
我认为CTCarrier有MCC和MNC。
您可以使用此问题中的代码检查网络类型: How to check if iPhone supports CDMA or GSM
看看CellID的这个问题: CTServerConnectionGetCellID routine core telephony
答案 2 :(得分:0)
以下代码是如何在ios 8.3上插入代码工作的权利。 从iOS 8.3开始,上述所有解决方案都需要工作权利
<key>com.apple.CommCenter.fine-grained</key>
<array>
<string>spi</string>
</array>
实际上,上面提到的代码据说可以运行以获得ios 8.3及以上版本的lac和cell。但我真的不知道如何在越狱手机上插入上述内容。任何人都可以提供任何详细信息。