Получите CellID, MCC, MNC, LAC и сеть в iOS 5.1 - программирование
Подтвердить что ты не робот

Получите CellID, MCC, MNC, LAC и сеть в iOS 5.1

Мне нужно получить CellID, MCC, MNC, LAC и сеть (GSM, 3G) текущей башни опорных ячеек в iOS 5.1 (iPhone 4S). Я знаю, что эта информация доступна, потому что я вижу ее в режиме FieldTest (доступный после вызова **** 3001 # 12345 # ****). Я полагаю, что он доступен через частные/недокументированные iOS-структуры.

В вопросе iphone, проверьте значения cellId/Lac, автор указывает, что я могу получить радиоинформацию cellId, Lac, MNC, MCC на iOS, но никакой информации о как это сделать.

Может кто-нибудь сказать мне, как получить эту информацию?

4b9b3361

Ответ 1

Я знаю три способа, как вы можете это сделать на iOS 5.x - 7.x. Все они используют частные API из CoreTelephony.framework. Поддерживает как 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];

UPDATE

В ARM64 (iPhone 5S) есть проблема со всеми функциями CoreTelephony, которые принимают аргумент struct CTResult. По-видимому, 64-разрядная версия CoreTelephony экспортирует эти функции без аргумента struct CTResult. Из-за этого вы получите сообщение об ошибке ARM64, если вы вызываете эти функции, как вы делали в прошлом, - аргументы будут неправильными. Я обновил объявления функций, чтобы они работали как на 32-битной, так и на 64-битной архитектуре ARM. Я тестировал его, и он работает как на iPhone 4S, так и на iPhone 5S.

Это относится только к ARM64. Если вы создадите проект для 32-битной архитектуры ARM, то такой проблемы нет. Ваше приложение будет использовать 32-битную версию CoreTelephony, которая ожидает аргумент struct CTResult.

8.3 UPDATE

Как и в iOS 8.3, все перечисленные выше решения требуют права на работу

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

Не только ядровый монитор защищен, но, похоже, все уведомления CoreTelephony теперь требуют права на работу. Например, kCTMessageReceivedNotification также затронул.

Ответ 2

suscriberCellularProvider - это метод объекта (метод класса vs).

Вы можете посмотреть, как его использовать здесь: Определить страну пользователя iPhone

Я думаю, что CTCarrier имеет MCC и MNC.

Вы можете проверить тип сети, используя код из этого вопроса: Как проверить, поддерживает ли iPhone CDMA или GSM.

И посмотрите этот вопрос для CellID: CTServerConnectionGetCellID обычная основная телефония

Ответ 3

Ниже приведен код, чтобы вставить в него право на использование кода в ios 8.3. Начиная с iOS 8.3 все вышеперечисленные решения требуют права на работу

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

Действительно, упомянутый выше упомянутый выше код можно запустить, чтобы получить lac и cell на ios 8.3 и выше. Но я действительно не знаю, как вставить выше на телефон с взломом. Может ли кто-нибудь дать подробную информацию.