web-dev-qa-db-ja.com

デバイスが通話をサポートしているかどうかを検出していますか?

以下のコードは、デバイスが通話をサポートできるかどうかを判断するために使用できますか?私の懸念は、Apple= iphone文字列を他の文字列に変更するかどうかです。たとえば、 "iphone 3g"、 "iphone 4"などを使用すると決めたとします。

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

IPhoneはtel:// URIスキームをサポートしています。だからあなたは使うことができます:

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

canOpenURL:そのURLスキームを開くことができるアプリケーションがあるかどうかを明示的にチェックします。URLが正しいかどうかはチェックしません。したがって、電話番号が指定されていなくてもかまいません。メソッドはBOOLを返すため、YESまたはNOかどうかを確認します。

これは、電話をかけることができるアプリケーションが存在するかどうかを文字通り答えるべきです。したがって、デバイスセグメンテーションの将来の変更に対しては問題ありません。

98
Tommy

デバイスが通話を「サポート」しているかどうかを確認するだけでは、達成しようとしていることによっては、物事に取り組む最善の方法ではない場合があります。信じられないかもしれませんが、古い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カードを取り外すと、mobileNetworkCodeが65535に設定されているようです。その理由は100%わかりません。

64
AlBeebe

私は、クライアントからの録音が電話の着信によって妨げられないようにする必要があるため、機内モードに移行するように促しますが、Wi-Fiはオンにします。上記の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

11
flo von der uni

@ the-guardianの応答に基づいて、私は次のことを思いつきました(Swift):

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 Simulator、iPhone 6S Plusでテストされており、適切に動作するようです。 iPadでモバイルデータをすぐに決定します。

10
Campbell_Souped

この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()
        }

このようにして、デバイスが通話をサポートしているかどうかを確認できます。

2
user5886755

デバイス名は将来変更される可能性があるため、あなたの方法は信頼できないと思います。アプリがiPhone以外のデバイスで実行されるのを防ぐことが懸念である場合は、Info.plistの IRequiredDeviceCapabilities 辞書に「テレフォニー」を追加できます。これにより、iPhone以外のデバイスがApp Storeからアプリをダウンロードできなくなります。

または、特定の瞬間に3G接続を確認する必要がある場合は、Appleの Reachability ユーティリティクラスを使用して、現在の3G/WIFI接続ステータスを確認できます。

2
Julio Gorgé

一般的にそうだと思います。私はより一般的な文字列比較を行います(将来の更新の場合に備えてより安全にするためです)。問題なく使用しました(これまでのところ...)。

デバイスが実際に電話をかけることができるかどうかをより確実にしたい場合は、Core Telephony APIも利用する必要があります。 CTCarrierクラスは、特定の瞬間に実際に電話をかけることができるかどうかを通知します。

2
Nick Toumpelis

電話番号を呼び出して、電話機能のないデバイスでエラーを表示するように依頼する場合:

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

            }
        }
0
Anton Tropashko