Моя цель - открыть свой CallViewController после того, как пользователь ответит на звонок. Я прочитал здесь несколько выдержек из SO, которые можно сделать, используя:
- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
NSLog(@"performAnswerCallAction");
}
- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
NSLog(@"performStartCallAction");
}
Приведенный выше код находится внутри AppDelegate.
Однако при использовании NSLogs эти методы вообще не запускаются. Кажется, я не могу найти никаких руководств по реализации с использованием Objective-C, которые легко понять с точки зрения новичка. Буду признателен за любые идеи, спасибо!
прием звонка @RJVKumar





Во-первых, вы установили делегат 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? Благодарность
Я обновил свой ответ с помощью фрагмента Objective-C.
Мики, я пробовала сделать фрагмент, который ты предоставил. AppDelegate соответствует CXProviderDelegate, также реализовал свои методы делегирования, но мои журналы на performAnswerCallAction по-прежнему не отображаются. Есть идея?
также, имеет ли значение строка initWithLocalizedName: @ "MyApp"? Или подойдет любая строка?
Что ж, я думаю, вам нужно указать локализованное имя для CallKit. Если вы инициализируете CXProviderConfiguration с локализованным именем или предоставите его позже, я все еще думаю, что это необходимо. Имя, которое вы вводите, будет отображаться под номером телефона, когда система отображает экран входящего вызова VoIP, а также в истории вызовов собственного приложения «Телефон». Я добавил в свой ответ комментарии, когда будут вызваны эти две функции.
Вы звоните или получаете звонок?