it-swarm.com.ru

Определяет, поддерживает ли устройство телефонные звонки?

Надежен ли приведенный ниже код для определения, может ли устройство поддерживать телефонные звонки или нет? Меня беспокоит, если Apple изменит строку iphone на что-то еще, скажем, они решат иметь «iphone 3g», «iphone 4» и т.п.

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

IPhone поддерживает схему tel: // URI. Таким образом, вы можете использовать:

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

canOpenURL: явно проверяет, есть ли приложение, способное открыть эту схему URL, а не то, что URL правильный. Поэтому не имеет значения, что номер телефона не указан. Метод возвращает BOOL, поэтому проверьте это для ДА или НЕТ.

Это должно буквально ответить на вопрос, есть ли какое-либо приложение, способное сделать телефонный звонок. Так что это должно быть хорошо против любых будущих изменений в сегментации устройства.

96
Tommy

Простая проверка того, поддерживает ли устройство телефонные звонки, может быть не лучшим способом решения проблем, в зависимости от того, что вы пытаетесь выполнить. Верьте или нет, некоторые люди используют старые айфоны без обслуживания, как если бы они были iPod Touch. Иногда люди не имеют SIM-карты, установленные в их iPhone. В моем приложении я хотел набрать номер телефона, если устройство пользователя могло, в противном случае я хотел бы отобразить номер телефона и предложить пользователю взять телефон и набрать его. Вот решение, которое я придумала, которое сработало до сих пор. Не стесняйтесь комментировать и улучшать его.

// 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%, почему это так.

62
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, и вы получите нулевое/нулевое значение, когда нет соединения с вышкой сотовой связи.

Вот где я его нашел: 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-карту, или Not not, она просто скажет, есть ли у устройства параметры для совершения вызова. Например : iPhone с SIM-картой или без нее будет возвращать значение 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, вы можете добавить «телефонию» в словарь UIRequiredDeviceCapabilities в вашем Info.plist. Это запретит другим устройствам, кроме iPhone, загружать ваше приложение из App Store.

В качестве альтернативы, если вам нужно проверить наличие соединения 3G в определенный момент, вы можете использовать класс утилит Apple Reachability , чтобы узнать о текущем состоянии соединения 3G/WIFI.

2
Julio Gorgé

Я думаю, что в целом это так. Я бы пошел для более общего сравнения строк (просто, чтобы быть более безопасным в случае будущего обновления). Я использовал это без проблем (пока ...). 

Если вы хотите быть более уверенным в том, может ли устройство на самом деле совершать звонки, вам также следует воспользоваться API-интерфейсом Core Telephony. Класс CTCarrier может сказать вам, можете ли вы действительно сделать звонок в любой конкретный момент.

2
Nick Toumpelis

В случае, если вы запрашиваете, чтобы позвонить по номеру телефона и показатьAn ошибка на устройствах, которые не имеют телефонии:

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