检测设备是否支持电话?

时间:2011-02-23 18:00:29

标签: ios objective-c iphone cocoa-touch phone-call

以下代码是否可靠用于确定设备是否可以支持电话? 我担心的是,如果苹果将iphone字符串更改为其他任何内容,我们可以说他们决定使用“iphone 3g”,“iphone 4”等。

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

9 个答案:

答案 0 :(得分:97)

iPhone支持tel:// URI方案。所以你可以使用:

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

canOpenURL:显式检查是否有能够打开该URL方案的应用程序,而不是URL是否正确。所以没有指定电话号码也没关系。该方法返回BOOL,因此请检查是否为NO。

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

答案 1 :(得分:64)

只需检查设备是否支持"根据你想要完成的事情,打电话可能不是最好的办法。信不信由你,有些人使用旧的iPhone没有服务,就像他们是iPod Touch一样。有时人们不会在他们的iPhone中安装SIM卡。在我的应用程序中,如果用户设备能够,我想拨打电话号码,否则我想显示电话号码并提示用户抓住电话并拨打电话。这是我提出的一个迄今为止有效的解决方案。随意评论并改进它。

// 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.在我的测试中,当您移除SIM卡时,似乎移动网络代码设置为65535.不是100%确定为什么会这样。

答案 2 :(得分:11)

我需要确保拨入的电话不会中断我的客户拨打的录音,因此我提示他们进入飞行模式但仍然打开wifi。 AlBeebe的上述方法在iOS 8.1.3上对我不起作用,但是如果发现这个解决方案应该适用于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];

然后当它发生变化时你会收到回调:

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

currentRadioAccessTechnology的值定义于 CTTelephonyNetworkInfo.h,当没有单元塔连接时,你将返回null / nil。

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

答案 3 :(得分:10)

基于@ the-guardian的回复,我提出了以下内容(快速):

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 = URL(string: "tel://") else {
        return false
    }

    let mobileNetworkCode = CTTelephonyNetworkInfo().subscriberCellularProvider?.mobileNetworkCode

    let isInvalidNetworkCode = mobileNetworkCode == nil
        || mobileNetworkCode?.count == 0
        || mobileNetworkCode == "65535"

    return UIApplication.shared.canOpenURL(url)
        && !isInvalidNetworkCode
}

此代码已经在iPad Air 2 Wifi,iPad Air 2模拟器,iPhone 6S Plus上进行了测试,似乎运行正常。很快就会在iPad上确定移动数据。

答案 4 :(得分:2)

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

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

答案 5 :(得分:2)

我认为通常是这样。我会寻求更通用的字符串比较(以便在将来更新时更安全)。我使用它没有问题(到目前为止......)。

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

答案 6 :(得分:2)

这个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()
        }

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

答案 7 :(得分:0)

如果您要求拨打电话号码并显示 没有电话的设备出错:

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

            }
        }

答案 8 :(得分:-1)

基于@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
    }