在iOS 5.1中获取手机基站ID、移动国家码、移动网络码、位置区码和网络信息

18

我需要获取 iOS 5.1 (iPhone 4S) 当前服务小区的 CellID、MCC、MNC、LAC 和网络 (GSM、3G)。我知道这些信息是可用的,因为在调用 ****3001#12345#**** 后可以在 FieldTest 模式中看到它们。我认为可以通过私有/未记录的 iOS 框架进行访问。

在问题iphone, check values of cellId / Lac中,作者指出 我可以在 iOS 上获取无线电信息 cellId、Lac、MNC、MCC,但没有提供如何做到这一点的信息。

有人能告诉我如何获取此信息吗?


2
对于MNC和MCC:https://dev59.com/questions/t0bRa4cB1Zd3GeqP5fyN - Rok Jarc
你的项目里是否包含了CoreTelephony.framework,并且已经导入了它的头文件? - Rok Jarc
1
我明白了!只是打错了一个字母...我调用了 suscriberCellularProvider 而不是 subscriberCellularProvider 现在它可以为 MNC 和 MCC 工作了...现在我需要获取 CellID 和 LAC,这可能会有一些困难... - poorDeveloper
@rokjarc,您能获取小区ID和位置区码吗?如果可以的话,您能告诉我如何继续吗? - Dee
@poorDeveloper 你能获取到小区ID和RxValues吗? - Dee
显示剩余9条评论
3个回答

18
我知道三种在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函数都存在问题。显然,CoreTelephony的64位版本会导出这些函数时没有struct CTResult参数。因此,如果像过去一样调用这些函数,则在ARM64上会出现错误-参数将是错误的。我更新了函数声明,使它们适用于32位和64位ARM架构。我进行了测试,在iPhone 4S和iPhone 5S上都可以正常工作。

这仅适用于ARM64。如果您为32位ARM架构构建项目,则不存在此问题。您的应用程序将使用期望struct CTResult参数的32位版本的CoreTelephony。

8.3 更新

iOS 8.3版本开始,所有以上解决方案都需要授权才能工作。

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

不仅仅是单个单元监视器被保护,而且似乎所有的CoreTelephony通知现在都需要该权限才能工作。例如,kCTMessageReceivedNotification也受到影响。


这在iOS 7中仍然可以获取Cell ID吗? - davidOhara
是的,它在iOS7上进行了测试。 - creker
你到底是什么意思,自己声明它?! - davidOhara
2
有没有任何线索可以解决在iOS 8.3上的问题? - kml_ckr
1
@kml_ckr发布了解决方案。现在需要越狱才能运行。 - creker
显示剩余12条评论

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。但我真的不知道如何在越狱手机上插入上述代码。有人能提供详细信息吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接