【问题标题】:Know if iOS device has cellular data capabilities了解 iOS 设备是否具有蜂窝数据功能
【发布时间】:2011-10-29 09:29:18
【问题描述】:

我的应用中有一个“仅在 WiFi 上下载”的切换开关。但是,这种切换对于 iPod touch 或 WiFi-iPad 来说是没有用的。

有没有办法知道设备是否在代码中具有蜂窝数据功能?将来可以使用的东西也会很棒(例如,如果带有 3G 功能的 iPod touch 第 5 代问世)。

【问题讨论】:

  • 我为此提交了一个错误:openradar.appspot.com/9974175.
  • 为什么不编辑您的 info.plist 并在 UIRequiredDeviceCapabilities 中添加 3g
  • @Zhao 这不是必需的,只是想为纯 WiFi 用户隐藏一个切换。
  • 抱歉,没有真正理解您的问题。我检查了 Apple 的文档,没有密钥 3g 也没有 cellular radio 用于 UIRequiredDeviceCapabilities

标签: iphone objective-c ios uidevice cellular-network


【解决方案1】:

您好,您应该可以检查它是否有 pdp_ip0 接口

#import <ifaddrs.h>

- (bool) hasCellular {
    struct ifaddrs * addrs;
    const struct ifaddrs * cursor;
    bool found = false;
    if (getifaddrs(&addrs) == 0) {
        cursor = addrs;
        while (cursor != NULL) {
            NSString *name = [NSString stringWithUTF8String:cursor->ifa_name];
            if ([name isEqualToString:@"pdp_ip0"]) {
                found = true;
                break;
            }
            cursor = cursor->ifa_next;
        }
        freeifaddrs(addrs);
    }
    return found;
}

这不使用任何私有 API。

【讨论】:

  • 我找到了一个类似的答案here,它似乎非常强大。好主意!
  • 给定代码示例中有几个错误,但这个想法是合理的。我在编辑中提供了更正。
  • @DTs 已经更正了。确保你#import
【解决方案2】:

3G 本身似乎很难找到。您可以使用[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel://"]] 了解设备是否可以拨打电话。您可以使用Reachability 代码检查设备是否可以上网、时间段(以及可以当前发生的方法):

NetworkStatus currentStatus = [[Reachability reachabilityForInternetConnection] 
                               currentReachabilityStatus];

if(currentStatus == kReachableViaWWAN) // 3G

else if(currentStatus == kReachableViaWifi) // ...wifi

else if(currentStatus == kNotReachable) // no connection currently possible

..但除此之外,我认为您无法检查设备中是否存在 3G 调制解调器。***** 如果无法拨打电话,并且当前没有手机打开数据并关闭无线网络关闭,您将无法确定它是否支持 3G。

另一种方法(虽然不向前兼容,因此您可能不想这样做)是将设备型号与详尽列表进行比较,了解哪些型号中有 3G 调制解调器,如 here 所示。

***** 根据 Bentech 的回答,如果您想深入了解设备名称(如果 Apple 决定更改 3g 接口名称,这可能会停止工作而没有预先警告),请致电 getifaddrs 并检查pdp_ip0 接口。

【讨论】:

  • 我知道你列出的所有内容......前两个是不可接受的:这不是因为你不能打电话或你目前在 WiFi 上,所以你不能拥有蜂窝数据。第三个不是未来的证明......
  • 我很清楚,这就是为什么我的回答是“不,没有办法只检查 3G”。
  • 您应该选择第三个选项,默认为“是的,它有 3G”,然后随着新设备的推出进行更新。如果切换在没有 3G 的设备上无法执行任何操作,那么将来的设备看到它是无害的(并且您仍然有一些时间窗口来更新它们之前)。
【解决方案3】:

@bentech 的回答的 Swift 3.0 (UIDevice+Extension)

将此行添加到您的 BridgingHeader.h:

#import <ifaddrs.h>

其他地方:

extension UIDevice {
    /// A Boolean value indicating whether the device has cellular data capabilities (true) or not (false).
    var hasCellularCapabilites: Bool {
        var addrs: UnsafeMutablePointer<ifaddrs>?
        var cursor: UnsafeMutablePointer<ifaddrs>?

        defer { freeifaddrs(addrs) }

        guard getifaddrs(&addrs) == 0 else { return false }
        cursor = addrs

        while cursor != nil {
            guard
                let utf8String = cursor?.pointee.ifa_name,
                let name = NSString(utf8String: utf8String),
                name == "pdp_ip0"
                else {
                    cursor = cursor?.pointee.ifa_next
                    continue
            }
            return true
        }
        return false
    }
}

【讨论】:

  • 这对我有用。在 ipod(无蜂窝收音机)和手机上进行了测试。我所做的唯一更改是在无法确定蜂窝网络时(由于错误或任何原因)返回 nil:“guard getifaddrs(&addrs) == 0 else { return nil }”(并使返回类型可选)。
【解决方案4】:

在 iOS 6.1 中,我已经能够使用 Core Telephony 成功检查是否存在蜂窝基带功能。这适用于我测试过的所有 iPad:Verizon 服务已激活和未激活,AT&T 服务当前已停用,SIM 卡进出,以及仅支持 Wi-Fi 的 iPad。

我使用的代码如下所示:

CTTelephonyNetworkInfo* ctInfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier* carrier = ctInfo.subscriberCellularProvider;
self.hasWWANCapability = carrier != nil;

对于所有具有蜂窝基带硬件的 iPad,carrier 不为零。对于仅支持 Wi-Fi 的 iPad,carrier 为零。

【讨论】:

  • 这是不正确的,如果没有蜂窝访问,即使您的设备具有蜂窝功能,您也会得到 nil。 (用 iOS5.1.1 测试了第一台 iPad)
【解决方案5】:

我认为您应该可以使用CoreTelephony Framework

它确实表明它是供运营商使用的,所以我不确定它是否违反 TOS 访问它。

运营商可以使用此信息编写仅为自己的订阅者提供服务的应用程序

【讨论】:

  • 我没有看到任何说它仅供运营商使用;它看起来像是为了满足运营商的需求而提供的,但没有任何措辞表明它只适合他们。
【解决方案6】:

一种方法是询问用户的位置。当它尽可能准确时,您将知道设备是否有 GPS。所有具有 GPS 的设备都将具有 3G。而那些没有 GPS 的将不会有 3G。

【讨论】:

  • 您将其与什么进行比较才能做出此决定?
  • 获取该信息也是一个非常漫长和昂贵的过程。此外,在室内时,大多数 GPS 设备无论如何都使用 WiFi,因为在这些条件下精度更高。
【解决方案7】:

Apple 在此处提供了代码。 https://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html

您应该将 Reachability.h 和 Reachability.m 复制到您的项目并导入 Reachability.h 到你的班级,然后

Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];

while (networkStatus==NotReachable) {
    NSLog(@"not reachable");
//no  internet connection 
    return;
}
while (networkStatus==ReachableViaWWAN) {
    NSLog(@" ReachableViaWWAN ");
}

while (networkStatus==ReachableViaWiFi) {
    NSLog(@"ReachableViaWiFi");
}

【讨论】:

  • 这是为了知道当前的互联网连接是什么,而不是设备的功能。
【解决方案8】:

另一种方法是扩展此:https://github.com/monospacecollective/UIDevice-Hardware/blob/master/UIDevice-Hardware.m 与此:

-(bool) hasCellular:(NSString*)modelIdentifier {
    if ([modelIdentifier hasPrefix:@"iPhone"]) return YES;
    if ([modelIdentifier hasPrefix:@"iPod"]) return NO;

    if ([modelIdentifier isEqualToString:@"iPad1,1"])      return NO;
    if ([modelIdentifier isEqualToString:@"iPad2,1"])      return NO;
    if ([modelIdentifier isEqualToString:@"iPad2,2"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad2,3"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad2,4"])      return NO;
    if ([modelIdentifier isEqualToString:@"iPad2,5"])      return NO;
    if ([modelIdentifier isEqualToString:@"iPad2,6"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad2,7"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad3,1"])      return NO;
    if ([modelIdentifier isEqualToString:@"iPad3,2"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad3,3"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad3,4"])      return NO;
    if ([modelIdentifier isEqualToString:@"iPad3,5"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad3,6"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad4,1"])      return NO;
    if ([modelIdentifier isEqualToString:@"iPad4,2"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad2,5"])      return NO;
    if ([modelIdentifier isEqualToString:@"iPad2,6"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad2,7"])      return YES;
    if ([modelIdentifier isEqualToString:@"iPad4,4"])      return NO;
    if ([modelIdentifier isEqualToString:@"iPad4,5"])      return YES;

    if ([modelIdentifier isEqualToString:@"i386"])         return NO;
    if ([modelIdentifier isEqualToString:@"x86_64"])       return NO;

return YES;

}

(很明显,它可以被编辑以删除 NO 或 YES,这取决于你想以哪种方式出错,以防万一有新模型......)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多