Методы CXProviderDelegate не вызываются

Моя цель - открыть свой CallViewController после того, как пользователь ответит на звонок. Я прочитал здесь несколько выдержек из SO, которые можно сделать, используя:

- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
    NSLog(@"performAnswerCallAction");
}

- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
     NSLog(@"performStartCallAction");
}

Приведенный выше код находится внутри AppDelegate.

Однако при использовании NSLogs эти методы вообще не запускаются. Кажется, я не могу найти никаких руководств по реализации с использованием Objective-C, которые легко понять с точки зрения новичка. Буду признателен за любые идеи, спасибо!

Вы звоните или получаете звонок?

RJV Kumar 01.10.2018 17:01

прием звонка @RJVKumar

Lysdexia 02.10.2018 03:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
2 423
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, вы установили делегат CXProvider?

let provider = CXProvider(configuration: your_call_kit_config)
provider.setDelegate(self, queue: nil) // 'nil' means it will run on main queue

Также убедитесь, что файл AppDelegate.swift соответствует CXProviderDelegate.

provider:performAnswerCallAction: вызывается, когда пользователь нажимает кнопку «Ответить» на экране входящего вызова, предоставляемом системой. (Документация Apple ЗДЕСЬ).

provider:performStartCallAction: вызывается после успешного запроса к CXCallController для выполнения CXStartCallAction (документация Apple ЗДЕСЬ).

РЕДАКТИРОВАТЬ: для цели-C

Хорошо, вот фрагмент Objective-C, например, в AppDelegate. Во-первых, вам нужно заставить AppDelegate соответствовать CXProviderDelegate, вот так:

@interface AppDelegate () <CXProviderDelegate>

Затем добавьте свойство для CXProvider и CXCallController, например:

@interface AppDelegate () <CXProviderDelegate>

@property (nonatomic, nonnull, strong) CXProvider *provider;
@property (nonatomic, nonnull, strong) CXCallController *callController;

@end

В функции приложение: willFinishLaunchingWithOptions: AppDelegate инициализируйте объект CXProvider конфигурацией вызова, например:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Setup CallKit
    CXProviderConfiguration *providerConfiguration = [[CXProviderConfiguration alloc] initWithLocalizedName:@"MyApp"];
    providerConfiguration.supportsVideo = YES;
    providerConfiguration.includesCallsInRecents = YES;
    self.provider = [[CXProvider alloc] initWithConfiguration: providerConfiguration];

    // Since `AppDelegate` conforms to `CXProviderDelegate`, set it to the provider object
    // Setting 'nil' to `queue` argument means, that the methods will be executed on main thread.
    // Optionally, you can assign private serial queue to handle `CXProvider` method responses
    [self.provider setDelegate:self queue:nil];

    // Initialize `CallController`
    self.callController = [[CXCallController alloc] init];

    return YES;

}

И в нижней части файла AppDelegate.m реализуйте методы CXProviderDelegate:

#pragma mark: - CXProvider delegate methods

- (void)providerDidReset:(CXProvider *)provider {
    // Drop all calls here (if there are pending)
}

/*!
 This method gets called when user presses on 'Accept' button on the incoming call screen provided by the system.
 Here you should configure `AVAudioSession` for VoIP calls and handle logic for answering the call.
 */
- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
    // Put your answering logic here
    // Note: It is important to fulfill the action inside the scope of it's function, or to fail, depending if error occured during answering
    [action fulfill];
}

/*!
 This method gets called when CXCallController object finishes the CXStartCallAction request. You need to request
 start call action to the CXCallController instance, when starting an outgoing VoIP call. After successful transaction,
 the provider will respond with this delegate method. Here you should also configure `AVAudioSession` for VoIP calls.
 */
- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
    // Put your outgoing call action here
    // Note: It is important to fulfill the action inside the scope of it's function, or to fail, depending if error occured during starting a call
    [action fulfill];
}

Чтобы начать исходящий вызов VoIP, вам необходимо запросить транзакцию с действием к экземпляру CXCallController, например так:

#pragma mark - Call Controller requests

- (void)startOutgoingVoIPCallWithNumber:(NSString *)number {
    NSUUID *callUUID = [NSUUID UUID]; // Here you create or assign UUID of call.
    CXHandle *callHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:number];
    CXStartCallAction *startCallAction = [[CXStartCallAction alloc] initWithCallUUID:callUUID handle:callHandle];
startCallAction.video = YES; // Yes or no is call is video or audio.

    CXTransaction *startCallTransaction = [[CXTransaction alloc] initWithAction:startCallAction];

    [self.callController requestTransaction:startCallTransaction completion:^(NSError * _Nullable error) {
        if (error) {
            // Handle start call error here
            // Ususally, error occurs if the system cannot handle the new outgoing call, since there are others pending
        }
        // If there is no error, CXProvider will respond with `provider:performStartCallAction:` method.
    }];
}

Отображение экрана системного вызова

#pragma mark - Report New incoming call

/*!
 You need to call this function each time you receive a new incoming call, usually right from the VoIP push notification.
 */
- (void)reportNewIncomingCallWithNumber:(NSString *)number {
    NSUUID *callUUID = [NSUUID UUID]; // Call UUID, you should have this in some Call object, not generating the new here
    CXHandle *callHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:number];
    CXCallUpdate *callInfo = [[CXCallUpdate alloc] init];
    callInfo.remoteHandle = callHandle;
    [self.provider reportNewIncomingCallWithUUID:[NSUUID UUID] update:callInfo completion:^(NSError * _Nullable error) {
        if (error) {
            // Handle error here
        }
        // If there is no error, system will display incoming call screen and when user taps on 'Answer',
        // `CXProvider` will respond with `provider:performAnswerCallAction:`
    }];
}

не могли бы вы привести пример этого с помощью ObjC? Благодарность

Lysdexia 18.10.2018 11:40

Я обновил свой ответ с помощью фрагмента Objective-C.

Miki 18.10.2018 22:54

Мики, я пробовала сделать фрагмент, который ты предоставил. AppDelegate соответствует CXProviderDelegate, также реализовал свои методы делегирования, но мои журналы на performAnswerCallAction по-прежнему не отображаются. Есть идея?

Lysdexia 19.10.2018 03:59

также, имеет ли значение строка initWithLocalizedName: @ "MyApp"? Или подойдет любая строка?

Lysdexia 19.10.2018 04:08

Что ж, я думаю, вам нужно указать локализованное имя для CallKit. Если вы инициализируете CXProviderConfiguration с локализованным именем или предоставите его позже, я все еще думаю, что это необходимо. Имя, которое вы вводите, будет отображаться под номером телефона, когда система отображает экран входящего вызова VoIP, а также в истории вызовов собственного приложения «Телефон». Я добавил в свой ответ комментарии, когда будут вызваны эти две функции.

Miki 19.10.2018 09:20

Другие вопросы по теме