Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym dokumencie omówimy sposób integracji biblioteki CallKit z aplikacją systemu iOS.
Wymagania wstępne
- Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
- Wdrożony zasób Usług Komunikacyjnych. Utwórz zasób usług komunikacyjnych.
- Token dostępu użytkownika umożliwiający włączenie klienta wywołującego. Aby uzyskać więcej informacji, zobacz Tworzenie tokenów dostępu i zarządzanie nimi.
- Opcjonalnie: ukończ przewodnik Szybki start, aby dodać połączenie głosowe do aplikacji
Integracja CallKit (w SDK)
Integracja zestawu CallKit w zestawie SDK usług Azure Communication Services dla systemu iOS obsługuje interakcję z zestawem CallKit dla nas. Aby wykonać wszystkie operacje wywołania, takie jak wyciszenie/odwyciszenie, zawieszenie/wznawianie, wystarczy wywołać interfejs API w zestawie SDK usług Azure Communication Services.
Inicjowanie agenta połączeń za pomocą opcji CallKitOptions
Przy użyciu skonfigurowanej instancji CallKitOptions możemy utworzyć element CallAgent z obsługą elementu CallKit.
let options = CallAgentOptions()
let callKitOptions = CallKitOptions(with: createProviderConfig())
options.callKitOptions = callKitOptions
// Configure the properties of `CallKitOptions` instance here
self.callClient!.createCallAgent(userCredential: userCredential,
options: options,
completionHandler: { (callAgent, error) in
// Initialization
})
Określanie informacji adresata połączenia dla połączeń wychodzących
Najpierw musimy utworzyć wystąpienie StartCallOptions() dla połączeń wychodzących lub JoinCallOptions() dla połączeń grupowych.
let options = StartCallOptions()
lub
let options = JoinCallOptions()
Następnie utwórz wystąpienie klasy CallKitRemoteInfo
options.callKitRemoteInfo = CallKitRemoteInfo()
- Przypisz wartość
callKitRemoteInfo.displayNameForCallKit, aby dostosować nazwę wyświetlaną odbiorcom połączeń i skonfigurować wartośćCXHandle. Ta wartość określona w parametrzedisplayNameForCallKitjest dokładnie taka, jak jest wyświetlana w ostatnim dzienniku połączeń telefonicznych. w ostatnim dzienniku połączeń telefonicznych.
options.callKitRemoteInfo.displayNameForCallKit = "DISPLAY_NAME"
- Przypisz wartość
cxHandle, którą aplikacja otrzymuje, gdy użytkownik oddzwania do tego kontaktu.
options.callKitRemoteInfo.cxHandle = CXHandle(type: .generic, value: "VALUE_TO_CXHANDLE")
Określanie informacji adresata połączenia dla połączeń przychodzących
Najpierw musimy utworzyć wystąpienie klasy CallKitOptions:
let callKitOptions = CallKitOptions(with: createProviderConfig())
Skonfiguruj właściwości CallKitOptions wystąpienia:
Blok przekazywany do zmiennej provideRemoteInfo zostanie wywołany przez SDK, gdy odbierzemy połączenie przychodzące i musimy uzyskać nazwę wyświetlaną dla rozmówcy, którą przekażemy do CallKit.
callKitOptions.provideRemoteInfo = self.provideCallKitRemoteInfo
func provideCallKitRemoteInfo(callerInfo: CallerInfo) -> CallKitRemoteInfo
{
let callKitRemoteInfo = CallKitRemoteInfo()
callKitRemoteInfo.displayName = "CALL_TO_PHONENUMBER_BY_APP"
callKitRemoteInfo.cxHandle = CXHandle(type: .generic, value: "VALUE_TO_CXHANDLE")
return callKitRemoteInfo
}
Konfigurowanie sesji audio
Konfiguracja sesji audio zostanie wywołana przed umieszczeniem lub zaakceptowaniem połączenia przychodzącego i przed wznowieniem połączenia po jego wstrzymaniu.
callKitOptions.configureAudioSession = self.configureAudioSession
public func configureAudioSession() -> Error? {
let audioSession: AVAudioSession = AVAudioSession.sharedInstance()
var configError: Error?
do {
try audioSession.setCategory(.playAndRecord)
} catch {
configError = error
}
return configError
}
UWAGA: W przypadkach, gdy firma Contoso skonfigurowała już sesje audio, nie udostępniaj nil, ale zwraca błąd nil w bloku.
callKitOptions.configureAudioSession = self.configureAudioSession
public func configureAudioSession() -> Error? {
return nil
}
jeśli podano nil dla configureAudioSession, to SDK wywołuje domyślną implementację w SDK.
Obsługa przychodzącego ładunku powiadomień push
Gdy aplikacja odbiera dane powiadomień push, musimy wywołać handlePush, aby je przetworzyć. Wywołanie zestawu SDK usług Azure Communication Services spowoduje wywołanie IncomingCall zdarzenia.
public func handlePushNotification(_ pushPayload: PKPushPayload)
{
let callNotification = PushNotificationInfo.fromDictionary(pushPayload.dictionaryPayload)
if let agent = self.callAgent {
agent.handlePush(notification: callNotification) { (error) in }
}
}
// Event raised by the SDK
public func callAgent(_ callAgent: CallAgent, didReceiveIncomingCall incomingcall: IncomingCall) {
}
Możemy użyć reportIncomingCall do obsługi powiadomień push, gdy aplikacja jest zamknięta lub w innej sytuacji.
if let agent = self.callAgent {
/* App is not in a killed state */
agent.handlePush(notification: callNotification) { (error) in }
} else {
/* App is in a killed state */
CallClient.reportIncomingCall(with: callNotification, callKitOptions: callKitOptions) { (error) in
if (error == nil) {
DispatchQueue.global().async {
self.callClient = CallClient()
let options = CallAgentOptions()
let callKitOptions = CallKitOptions(with: createProviderConfig())
callKitOptions.provideRemoteInfo = self.provideCallKitRemoteInfo
callKitOptions.configureAudioSession = self.configureAudioSession
options.callKitOptions = callKitOptions
self.callClient!.createCallAgent(userCredential: userCredential,
options: options,
completionHandler: { (callAgent, error) in
if (error == nil) {
self.callAgent = callAgent
self.callAgent!.handlePush(notification: callNotification) { (error) in }
}
})
}
} else {
os_log("SDK couldn't handle push notification", log:self.log)
}
}
}
Integracja z zestawem CallKit (w aplikacji)
Jeśli chcesz zintegrować zestaw CallKit w aplikacji i nie używać implementacji CallKit w zestawie SDK, zapoznaj się z przykładowym przewodnikiem Szybki start tutaj. Jedną z ważnych rzeczy, o które należy zadbać, jest rozpoczęcie dźwięku w odpowiednim czasie. Podobnie jak poniżej
let outgoingAudioOptions = OutgoingAudioOptions()
outgoingAudioOptions.muted = true
let incomingAudioOptions = IncomingAudioOptions()
incomingAudioOptions.muted = true
var copyAcceptCallOptions = AcceptCallOptions()
copyStartCallOptions.outgoingAudioOptions = outgoingAudioOptions
copyStartCallOptions.incomingAudioOptions = incomingAudioOptions
callAgent.startCall(participants: participants,
options: copyStartCallOptions,
completionHandler: completionBlock)
Wyciszenie głośnika i mikrofonu gwarantuje, że fizyczne urządzenia audio nie będą używane, aż CallKit wywoła didActivateAudioSession w CXProviderDelegate. W przeciwnym razie połączenie może zostać porzucone lub dźwięk nie będzie działać.
Kiedy didActivateAudioSession należy uruchomić strumienie audio.
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
Task {
guard let activeCall = await self.callKitHelper.getActiveCall() else {
print("No active calls found when activating audio session !!")
return
}
try await startAudio(call: activeCall)
}
}
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
Task {
guard let activeCall = await self.callKitHelper.getActiveCall() else {
print("No active calls found when deactivating audio session !!")
return
}
try await stopAudio(call: activeCall)
}
}
private func stopAudio(call: Call) async throws {
try await self.callKitHelper.muteCall(callId: call.id, isMuted: true)
try await call.stopAudio(stream: call.activeOutgoingAudioStream)
try await call.stopAudio(stream: call.activeIncomingAudioStream)
try await call.muteIncomingAudio()
}
private func startAudio(call: Call) async throws {
try await call.startAudio(stream: LocalOutgoingAudioStream())
try await self.callKitHelper.muteCall(callId: call.id, isMuted: false)
try await call.startAudio(stream: RemoteIncomingAudioStream())
try await call.unmuteIncomingAudio()
}
Ważne jest również wyciszenie wychodzącego dźwięku przed zatrzymaniem dźwięku w przypadkach, gdy zestaw CallKit nie wywołuje elementu didActivateAudioSession. Następnie użytkownik może ręcznie cofnąć wyciszenie mikrofonu.
Uwaga / Notatka
W niektórych przypadkach CallKit nie wywołuje didActivateAudioSession, mimo że aplikacja ma podwyższone uprawnienia do dźwięku, w takim przypadku dźwięk pozostanie wyciszony do czasu otrzymania wywołania zwrotnego. Interfejs użytkownika musi odzwierciedlać stan głośnika i mikrofonu. Zdalni uczestnicy w trakcie rozmowy zobaczą, że użytkownik również wyciszył dźwięk. W takich przypadkach użytkownik będzie musiał ręcznie cofnąć wyciszenie.