Retrieving Carrier Name from iPhone programmatically

浪子不回头ぞ 提交于 2019-11-26 17:15:53
George Zhu

In iOS 4, the CoreTelephony framework is useable, here's a snippet to get the carrier name:

CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = [netinfo subscriberCellularProvider];
NSLog(@"Carrier Name: %@", [carrier carrierName]);
[netinfo release];

Link against CoreTelephony and include in your headers:

#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>

Just to make a note here.. I tested this API on different SIMs and it seems that the name of the operator the iPhone is locked to is returned with [carrer carrierName]!!

I tested this on 2 iphones, one locked and the other not, and for the locked one, regardless of the SIM provider, it returns the name of the operator it is locked to everytime i run my test app. Note however that the MNC does change!

There is no public API for getting the carrier name. If you don't need to publish on the App Store you could look at using private api's.

VVCarrierParameters.h in the VisualVoiceMail package seems to have a carrierServiceName class method that might be what you need. Drop that header in your project and call [VVCarrierParameters carrierServiceName].

Note your app will most likely be rejected if you do this.

Get carrier name from status bar in case if Core Telephony returns "Carrier"

func getCarrierName() -> String? {

    var carrierName: String?

    let typeName: (Any) -> String = { String(describing: type(of: $0)) }

    let statusBar = UIApplication.shared.value(forKey: "_statusBar") as! UIView

    for statusBarForegroundView in statusBar.subviews {
        if typeName(statusBarForegroundView) == "UIStatusBarForegroundView" {
            for statusBarItem in statusBarForegroundView.subviews {
                if typeName(statusBarItem) == "UIStatusBarServiceItemView" {
                    carrierName = (statusBarItem.value(forKey: "_serviceString") as! String)
                }
            }
        }
    }
    return carrierName
}

While developing Alpha, I encountered the same problem. The project itself was not limited to use only public API, so first I tried @Jason Harwig's solution. Because I could not get it to work, I thought of another option.

My solution uses private API to access the _serviceString ivar of the label (UIStatusBarServiceItemView) that is displayed in status bar.

It relies on status bar having a carrier value and only needs UIKit to work.

- (NSString *)carrierName
{
    UIView* statusBar = [self statusBar];

    UIView* statusBarForegroundView = nil;

    for (UIView* view in statusBar.subviews)
    {
        if ([view isKindOfClass:NSClassFromString(@"UIStatusBarForegroundView")])
        {
            statusBarForegroundView = view;
            break;
        }
    }

    UIView* statusBarServiceItem = nil;

    for (UIView* view in statusBarForegroundView.subviews)
    {
        if ([view isKindOfClass:NSClassFromString(@"UIStatusBarServiceItemView")])
        {
            statusBarServiceItem = view;
            break;
        }
    }

    if (statusBarServiceItem)
    {
        id value = [statusBarServiceItem valueForKey:@"_serviceString"];

        if ([value isKindOfClass:[NSString class]])
        {
            return (NSString *)value;
        }
    }

    return @"Unavailable";
}

- (UIView *)statusBar
{
    NSString *statusBarString = [NSString stringWithFormat:@"%@ar", @"_statusB"];
    return [[UIApplication sharedApplication] valueForKey:statusBarString];
}

I only tested the method with applications that have status bar visible. It returns the same string as it is displayed in status bar, so it works correctly even when roaming.

This method is not App Store safe.

https://developer.apple.com/iphone/prerelease/library/documentation/NetworkingInternet/Reference/CTCarrier/Reference/Reference.html#//apple_ref/doc/uid/TP40009596-CH1-DontLinkElementID_3

There is a such way however it's only available on iOS 4 so you won't be able to use it on previous versions. And this probably breaks your backward compatibility too.

For swift users you can try this:

import CoreTelephony

static var carrierName:String? {
    let networkInfo = CTTelephonyNetworkInfo()
    let carrier = networkInfo.subscriberCellularProvider
    return carrier?.carrierName
}

When you print output of carrier?.description

This is what you see:

[\"0000000100000001\": CTCarrier (0x2803a1980) {\n\tCarrier name: [Vodafone]\n\tMobile Country Code: [214]\n\tMobile Network Code:[01]\n\tISO Country Code:[es]\n\tAllows VOIP? [YES]\n}\n]

Formatted (\n and \t):

[\"0000000100000001\": CTCarrier (0x2803a1980) {
    Carrier name: [Vodafone]
    Mobile Country Code: [214]
    Mobile Network Code:[01]
    ISO Country Code:[es]
    Allows VOIP? [YES]
}
]

So get carrier name from status bar is a good option (at least for me)

I mean the answer of "codethemall" user.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!