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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13399659/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:12:29  来源:igfitidea点击:

Get CellID, MCC, MNC, LAC, and Network in iOS 5.1

iosgsm3giphone-privateapicellid

提问by poorDeveloper

I need to retrieve CellID, MCC, MNC, LAC and Network (GSM, 3G) of the current Serving Cell Tower in iOS 5.1 (iPhone 4S). I know this information is available because I can see it in FieldTest Mode (accessible after calling ****3001#12345#****). I suppose it to be accessible via Private/Undocumented iOS Frameworks.

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

In the question iphone, check values of cellId / Lacthe author indicates I can get radio Informations cellId, Lac, MNC, MCC on iOS, but no information on how to do this is provided.

在问题iphone, check values of cellId / Lac 中,作者表示我可以在 iOS 上获取无线电信息 cellId, Lac, MNC, MCC,但没有提供有关如何执行此操作的信息。

Can anybody tell me how to get this info?

谁能告诉我如何获得这些信息?

回答by creker

I know three ways on how you can do it on iOS 5.x - 7.x. All of them use private APIs from CoreTelephony.framework. Supports both GSM and UMTS.

我知道如何在 iOS 5.x - 7.x 上执行此操作的三种方法。它们都使用来自 CoreTelephony.framework 的私有 API。支持 GSM 和 UMTS。

1) Using cell monitor

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) Using CTTelephonyCenter

2) 使用 CTTelephonyCenter

kCTRegistrationCellChangedNotificationis sent every time current serving cell tower is changed.

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) This returns current serving cell tower

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];

UPDATE

更新

On ARM64 (iPhone 5S) there is an issue with all CoreTelephony functions that accept struct CTResultargument. Apparently, 64-bit version of CoreTelephony exports these functions without struct CTResultargument. Because of that you will get an error on ARM64 if you call these functions like you did in the past - arguments will be wrong. I updated function declarations so that they work on both 32-bit and 64-bit ARM architectures. I tested it and it works on both iPhone 4S and iPhone 5S.

在 ARM64 (iPhone 5S) 上,所有接受struct CTResult参数的CoreTelephony 函数都存在问题。显然,64 位版本的 CoreTelephony 无需struct CTResult参数即可导出这些函数。因此,如果您像过去那样调用这些函数,则会在 ARM64 上出现错误 - 参数将是错误的。我更新了函数声明,以便它们可以在 32 位和 64 位 ARM 架构上工作。我测试了它,它适用于 iPhone 4S 和 iPhone 5S。

This only applies to ARM64. If you build your project for 32-bit ARM architecture then there is no such issue. Your application will use 32-bit version of CoreTelephony which expects struct CTResultargument.

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

8.3 UPDATE

8.3 更新

As of iOS 8.3 all of the above solutions require entitlement to work

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

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

Not only cell monitor is protected but it seems like all of the CoreTelephony notifications now require that entitlement to work. For example, kCTMessageReceivedNotificationalso affected.

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

回答by Victor Ronin

suscriberCellularProvider is an object method (vs class method).

suscriberCellularProvider 是一个对象方法(相对于类方法)。

You can take a look how to use it here: Determine iPhone user's country

您可以在此处查看如何使用它: 确定 iPhone 用户所在的国家/地区

I think CTCarrier has MCC and MNC.

我认为 CTCarrier 有 MCC 和 MNC。

You can check network type using the code from this question: How to check if iPhone supports CDMA or GSM

您可以使用以下问题中的代码检查网络类型: 如何检查 iPhone 是否支持 CDMA 或 GS​​M

And look this question for CellID: CTServerConnectionGetCellID routine core telephony

并查看 CellID 的这个问题: CTServerConnectionGetCellID 例程核心电话

回答by cellmap

The code below is how to insert to che entitlement to meke the code work on ios 8.3. As of iOS 8.3 all of the above solutions require entitlement to work

下面的代码是如何插入 che 权限以让代码在 ios 8.3 上工作。从 iOS 8.3 开始,上述所有解决方案都需要授权才能工作

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

Indeed, tha above code mentioned is said that can be run to get the lac and cell on ios 8.3 and above. But I really don't know how to insert the above on a jailbroken phone. Could anyone give any detail information.

确实,上面提到的代码据说可以在ios 8.3及更高版本上运行以获取lac和cell。但我真的不知道如何在越狱的手机上插入上述内容。任何人都可以提供任何详细信息。