从iPhone程序中以编程方式检索运营商名称

50

有没有一种程序化的方式来了解 iPhone 所使用的蜂窝运营商?

我正在寻找 iPhone 连接的运营商名称。


5
你的意思是除了AT&T,还有其他的iPhone运营商?<g/d/r> - Joel Coehoorn
你是在谈论手机当前连接的服务提供商(即可能正在漫游),还是谁是你收到账单的运营商? - crashmstr
15
你可能没有听说过,但世界上还有其他国家。有趣的是,它们也拥有移动技术。 - mentat
4
再次提醒大家保持幽默感。 - Shane C. Mason
唯一检测漫游的机制是通过读取一个未记录的系统文件请参见上一个问题,这违反了苹果的规定。 - joneswah
11个回答

84

iOS 4版本中,可以使用CoreTelephony框架,以下是获取运营商名称的代码片段:

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

链接 CoreTelephony 并将其包含在您的头文件中:

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

13
根据苹果的文档,这总是提供有关您所属的本地运营商的信息,而不是您正在漫游时连接的运营商的信息。 - phoenies
对于运营商名称,仅使用“Carrier”,不要使用如Verizon等名称。 - Jafar Khoshtabiat
现在CTCarrier已经被弃用。https://developer.apple.com/documentation/coretelephony/ctcarrier。我想知道这个的替代方法是什么?我没有找到替代API。 - Rohit Singh
@RohitSingh 可能是 CTTelephonyNetworkInfo.serviceSubscriberCellularProviders 吗?它返回一个 CTCarrier 字典,而且没有被弃用... https://developer.apple.com/documentation/coretelephony/cttelephonynetworkinfo/3024511-servicesubscribercellularprovide - Michael

15

仅做记录..我在不同的SIM卡上测试了这个API,似乎iPhone锁定的运营商名称是通过[carrer carrierName]返回的!!

我在两台iPhone上测试了这一点,一台是被锁定的,另一台没有,对于被锁定的那一台,无论SIM卡提供商如何,每次运行我的测试应用程序都会返回它所锁定的运营商名称。但请注意,MNC确实会改变!


1
好的评论。在看到这个回复之前我不知道这一点。可以确认我也遇到了同样的问题 - carrierName返回的是锁定运营商的名称,而不是SIM卡运营商的名称。 - Ian L
在iOS 7上进行测试,解锁手机:始终返回“Carrier”作为carrierName。因此,无法正确地确定手机中的运营商。返回的字符串等于在“设置”->“通用”->“关于本机”下显示的字符串。但是版本号已丢失。 - Legoless
这是正确的。MNC是从CTCarrier获取运营商的唯一准确测试。我们也缓存MNC值,因为如果用户没有网络连接、处于飞行模式或已移除他们的SIM卡,它将返回nil。 - NSAlexC

5

4
对于Swift用户,您可以尝试以下方法:
import CoreTelephony

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

carrier?.carrierName 目前不存在。 - Markus
目前存在运营商描述吗? - Markus
carrier?.description的输出:["0000000100000001": CTCarrier (0x2803a1980) {\n\t运营商名称:[Vodafone]\n\t移动国家代码:[214]\n\t移动网络代码:[01]\n\tISO国家代码:[es]\n\t允许VOIP? [是]\n}\n] - Markus

2
没有公共API可用于获取载波名称。如果您不需要在应用商店上发布,可以考虑使用私有API。
VisualVoiceMail包中的VVCarrierParameters.h似乎有一个carrierServiceName类方法,可能是您所需的。将该头文件添加到您的项目中,并调用[VVCarrierParameters carrierServiceName]
请注意,如果这样做,您的应用程序很可能会被拒绝。

1

在开发 Alpha时,我遇到了同样的问题。该项目本身不限于仅使用公共API,因此首先尝试了@Jason Harwig的解决方案。由于我无法使其工作,所以考虑了另一个选项。

我的解决方案使用私有API访问标签(UIStatusBarServiceItemView)中显示在状态栏中的_serviceString ivar。

它依赖于状态栏具有载体值,并且只需要UIKit即可工作。

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

我只测试了状态栏可见的应用程序。它返回与状态栏中显示的字符串相同的字符串,因此即使在漫游时也可以正常工作。
这种方法不适用于App Store。

1
从状态栏中获取运营商名称,如果核心电信返回“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
}

这个方法是否安全可靠,可以在App Store上使用吗? - Andrey Gagan

1

如果您使用的是Swift和iOS 12.0及以下版本,请执行以下操作:

导入CoreTelephony

static var carrierName:String? {
    CTTelephonyNetworkInfo().serviceSubscriberCellularProviders?.first?.value.carrierName ?? ""
}

0

当您打印carrier?.description的输出时

这是您看到的:

[\"0000000100000001\": CTCarrier (0x2803a1980) {\n\t运营商名称:[Vodafone]\n\t移动国家代码:[214]\n\t移动网络代码:[01]\n\tISO国家代码:[es]\n\t允许VOIP?[是]\n}\n]

格式化后(\n和\t):

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

从状态栏获取运营商名称是一个不错的选择(至少对我来说是这样)

我的意思是“codethemall”用户的答案。


0

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