检测设备是否支持电话?

以下代码是否可靠用于确定设备是否可以支持电话呼叫? 我关心的是,如果苹果改变iPhone的string,让我们说,他们决定有“iPhone 3G”,“iPhone 4”等

[[UIDevice currentDevice].model isEqualToString:@"iPhone"] 

iPhone支持tel:// URIscheme。 所以你可以使用:

 [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel://"]]; 

canOpenURL:明确检查是否有能够打开该URLscheme的应用程序,而不是该URL是否正确。 所以不要指定电话号码。 该方法返回一个BOOL,所以检查是或否。

这应该从字面上回答是否有任何应用程序能够打电话。 所以对未来设备细分的变化应该没问题。

简单地检查设备“支持”电话呼叫可能不是最好的方式去取决于你想要完成的事情。 信不信由你,某些人使用旧iPhone而没有服务,就好像他们是iPod Touch一样。 有时候人们没有在他们的iPhone上安装SIM卡。 在我的应用程序中,我想拨打一个电话号码,如果用户设备能够,否则我想显示电话号码,并提示用户抓住一个电话,并拨打它。 这是我提出的一个解决scheme,迄今为止工作。 随意评论和改进。

 // You must add the CoreTelephony.framework #import <CoreTelephony/CTTelephonyNetworkInfo.h> #import <CoreTelephony/CTCarrier.h> -(bool)canDevicePlaceAPhoneCall { /* Returns YES if the device can place a phone call */ // Check if the device can place a phone call if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel://"]]) { // Device supports phone calls, lets confirm it can place one right now CTTelephonyNetworkInfo *netInfo = [[[CTTelephonyNetworkInfo alloc] init] autorelease]; CTCarrier *carrier = [netInfo subscriberCellularProvider]; NSString *mnc = [carrier mobileNetworkCode]; if (([mnc length] == 0) || ([mnc isEqualToString:@"65535"])) { // Device cannot place a call at this time. SIM might be removed. return NO; } else { // Device can place a phone call return YES; } } else { // Device does not support phone calls return NO; } } 

你会注意到我检查了mobileNetworkCode是否是65535.在我的testing中,看起来,当你删除SIM卡时,mobileNetworkCode被设置为65535.不是100%确定这是为什么。

我需要确保来电不能中断我的客户录制的内容,所以我提示他们去飞机模式,但仍然打开wifi。 AlBeebe上面的方法在iOS 8.1.3上不适合我,但是如果发现这个解决scheme应该在iOS 7和更高版本中工作:

您必须添加并导入CoreTelephony.framework。

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

如果要跟踪更改,请定义类上的属性

 @property (strong, nonatomic) CTTelephonyNetworkInfo* networkInfo; 

初始化CTTelephonyNetworkInfo

 self.networkInfo = [[CTTelephonyNetworkInfo alloc] init]; NSLog(@"Initial cell connection: %@", self.networkInfo.currentRadioAccessTechnology); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(radioAccessChanged) name:CTRadioAccessTechnologyDidChangeNotification object:nil]; 

然后当它改变时你会收到callback:

 - (void)radioAccessChanged { NSLog(@"Now you're connected via %@", self.networkInfo.currentRadioAccessTechnology); } 

currentRadioAccessTechnology的值是在CTTelephonyNetworkInfo.h中定义的,当没有信元塔连接时,你会得到null / nil。

这是我find它的地方: http : //www.raywenderlich.com/48001/easily-overlooked-new-features-ios-7

基于@监护人的回应,我提出了以下(迅速):

 import CoreTelephony /** Indicates if the device can make a phone call. - seealso: [Source](http://stackoverflow.com/a/11595365/3643020) - returns: `true` if the device can make a phone call. `false` if not. */ final class func canMakePhoneCall() -> Bool { guard let URL = NSURL(string: "tel://") else { return false } let mobileNetworkCode = CTTelephonyNetworkInfo().subscriberCellularProvider?.mobileNetworkCode let isInvalidNetworkCode = mobileNetworkCode == nil || mobileNetworkCode?.characters.count == 0 || mobileNetworkCode == "65535" return UIApplication.sharedApplication().canOpenURL(URL) && !isInvalidNetworkCode } 

此代码已经在iPad Air 2 Wifi,iPad Air 2模拟器,iPhone 6S Plus上进行了testing,似乎正常工作。 即将在移动数据的iPad上确定。

UIApplication.shared.openURL((URL(string: "tel://\(phoneNumber)")!))不会说,如果它有SIM卡或不这将只是说,如果设备有选项来拨打电话。 例如 :有或没有SIM卡的iPhone会返回true,但是在iPod Touch中它总是会返回false,如果ipad没有sim选项,它将返回false。

这里是全面检查一切的代码! (使用Swift 3.0)

 if UIApplication.shared.canOpenURL(URL(string: "tel://\(phoneNumber)")!) { var networkInfo = CTTelephonyNetworkInfo() var carrier: CTCarrier? = networkInfo.subscriberCellularProvider var code: String? = carrier?.mobileNetworkCode if (code != nil) { UIApplication.shared.openURL((URL(string: "tel://\(phoneNumber)")!)) } else { var alert = UIAlertView(title: "Alert", message: "No SIM Inserted", delegate: nil, cancelButtonTitle: "ok", otherButtonTitles: "") alert.show() } } else { var alert = UIAlertView(title: "Alert", message: "Device does not support phone calls.", delegate: nil, cancelButtonTitle: "ok", otherButtonTitles: "") alert.show() } 

通过这种方式,我们可以确定,设备是否支持呼叫。

我不认为你的方法是可靠的,因为设备名称将来可能会改变。 如果您的担心是阻止应用程序在非iPhone设备上运行,则可以将“电话”添加到Info.plist中的UIRequiredDeviceCapabilities字典中。 这将不允许iPhone以外的设备从App Store下载您的应用程序。

或者,如果您需要的是在特定时刻检查3G连接,则可以使用Apple的Reachability实用程序类来询问当前的3G / WIFI连接状态。

我认为这是普遍的。 我会去一个更通用的string比较(只是为了更安全的情况下未来的更新)。 我用它没有问题(到目前为止…)。

如果您想更确定设备是否可以拨打电话,您还应该利用核心电话API。 CTCarrier课程可以告诉你,你是否可以在任何特定的时刻打电话。

如果您要求拨打电话号码并在没有电话的设备上显示错误,请执行以下操作:

 void openURL(NSURL *url, void (^ __nullable completionHandler). (BOOL success)) { if (@available(iOS 10.0, *)) { [application openURL:url options:@{} completionHandler:^(BOOL success) { completionHandler(success); }]; } else { if([application openURL:url]) { completionHandler(YES); } else { completionHandler(NO); } } } 

用法

  p97openURL(phoneURL, ^(BOOL success) { if(!success) { show message saying there is no telephony on device } } 

基于@TheGuardian的回答,我认为这可能是一个更简单的方法:

  private final func canMakePhoneCall() -> Bool { guard UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Phone else { return false } let mobileNetworkCode = CTTelephonyNetworkInfo().subscriberCellularProvider?.mobileNetworkCode let isInvalidNetworkCode = mobileNetworkCode == nil || mobileNetworkCode?.characters.count <= 0 || mobileNetworkCode == "65535" //When sim card is removed, the Code is 65535 return !isInvalidNetworkCode }